美文网首页
软件工程作业的一些说明

软件工程作业的一些说明

作者: 啦啦哇哈哈 | 来源:发表于2019-05-05 22:45 被阅读0次

软件工程作业要求写一款APP,安卓的应用开发也一直是自己的兴趣,所以整个作业的完成过程中还是很兴奋的。我们的APP是基于gank.io网站提供的文章数据接口,和美女图片接口,完成的一款开发技术干货APP,下面简单说一下完成作业过程中值得说的几个点。

MVC架构

作业要求使用MVC架构,MVC是Model-View-Controller的简写,在android里面,MVC很好理解,

  • Model是一个个数据实体类,它承载了应用中的数据,我们的APP中包括:用户的数据实体类User,封装的网络请求类(net包下的),文章的数据实体类GankModel,收藏的实体类SaveModel以及一些其他的常量类,和一些View的Adapter类,应该都属于Model层,Model为视图界面(View)层提供了根本的东西:


  • View就是用户能直接看到的视图界面,就对应android里面的一个个View,界面的布局写在xml文件里面,我们的App里面自定义的View就只有一个EmptyRecyclerView,处理了一些没有数据的空页面的情况,剩下的View都是用的是Android SDK中的UI控件,能够顺利完成我们的需求了:



    下面是很多布局文件,我们所有的视图都依赖这些xml:



    简单看一个其中的例子:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:background="@color/gray"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".controller.activity.LoginActivity">


    <ScrollView
        android:id="@+id/login_form"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <LinearLayout
            android:padding="10dp"
            android:id="@+id/email_login_form"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <ImageView
                android:layout_gravity="center_horizontal"
                android:src="@drawable/icon_app_ironman"
                android:id="@+id/iv_login_icon"
                android:layout_width="150dp"
                android:layout_height="150dp" />

            <TextView
                android:layout_marginTop="10dp"
                android:layout_gravity="center_horizontal"
                android:id="@+id/tv_welcome"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="18sp"
                android:textStyle="italic|bold"
                android:text="欢迎来到干货营!"/>
            <android.support.design.widget.TextInputLayout
                android:layout_marginTop="10dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <AutoCompleteTextView
                    android:id="@+id/tv_account"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="@string/prompt_email"
                    android:inputType="textEmailAddress"
                    android:maxLines="1"
                    android:singleLine="true" />

            </android.support.design.widget.TextInputLayout>

            <android.support.design.widget.TextInputLayout
                android:layout_marginTop="10dp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <EditText
                    android:id="@+id/et_password"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="@string/prompt_password"
                    android:imeActionId="6"
                    android:imeOptions="actionUnspecified"
                    android:inputType="textPassword"
                    android:maxLines="1"
                    android:singleLine="true" />

            </android.support.design.widget.TextInputLayout>
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <CheckBox
                    android:id="@+id/cb_remember"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentRight="true"
                    android:text="记住密码" />
            </RelativeLayout>
            <Button
                android:id="@+id/btn_sign_in"
                android:elevation="10dp"
                android:background="@drawable/shape_login_btn"
                style="?android:textAppearanceSmall"
                android:textColor="@color/white"
                android:textSize="16sp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="16dp"
                android:text="@string/action_sign_in"
                android:textStyle="bold" />

            <Button
                android:id="@+id/btn_register"
                android:elevation="10dp"
                android:background="@drawable/shape_login_btn"
                style="?android:textAppearanceSmall"
                android:textColor="@color/white"
                android:textSize="16sp"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="16dp"
                android:text="@string/action_register"
                android:textStyle="bold" />
        </LinearLayout>
    </ScrollView>

这就是View层

  • Controller层自然就是安卓中最重要的Activity或者Fragment



    Controller顾名思义,它负责控制,相当于View层和Model层的中间层,View层的数据来源于Model层,它需要Controller层把Model的数据交给View,而用户的一些点击操作滑动操作可能改变Model层的数据,那也需要Controller层来扮演这个角色,将用户的操作转化成对数据的改变。典型的例子就是Activity中各种Button的setOnclickListener里面做的事情,就十分鲜明的说明了Activity作为Controller的作用。比如这是登录界面的两个Button的Listener:

        btn_register.setOnClickListener {
            startActivity(Intent(this, RegisterActivity::class.java))
        }
        btn_sign_in.setOnClickListener { onLogin() }

点击第一个Button注册,就跳转到注册的Activity,点击第二个Button登录,就进入登录状态,onLogin里面处理的登录的检查和跳转等等。

但事实上在写的过程中很难避免Activity或者Fragment要做一些视图的操作,比如setVisibility这些,因为xml几乎不具备可编程性。Controller层和View层的耦合还是比较严重的,所以其实有更好的一些其他的架构。。MVC这种模式事实上还是有很大的劣势的,至少在Android中是这样。

大概我们作业的结构就介绍完了:


下面再谈谈其他的几个点:

关于Kotlin

不得不说Kotlin包装的一些语法糖,吃起来真甜,目前还没有接触到多少Kotlin的高级特性,但是一些简单的特性,就已经让人爱不释手了。举个最简单的例子在Model层会有大量的数据实体类,我们拿最重要的这个GankModel举例子,Java语言是这样的:

public class GankModel {
    private boolean error;
    private List<ResultsEntity> results;

    public void setError(boolean error) {
        this.error = error;
    }

    public void setResults(List<ResultsEntity> results) {
        this.results = results;
    }

    public boolean getError() {
        return error;
    }

    public List<ResultsEntity> getResults() {
        return results;
    }

    public static class ResultsEntity implements Serializable{
        public ResultsEntity() {
        }

        public ResultsEntity(String _id, String createdAt, String desc, String publishedAt, String source, String type, String url, boolean used, String who, List<String> images) {
            this._id = _id;
            this.createdAt = createdAt;
            this.desc = desc;
            this.publishedAt = publishedAt;
            this.source = source;
            this.type = type;
            this.url = url;
            this.used = used;
            this.who = who;
            this.images = images;
        }

        private String _id;
        private String createdAt;
        private String desc;
        private String publishedAt;
        private String source;
        private String type;
        private String url;
        private boolean used;
        private String who;
        private List<String> images;

        public void set_id(String _id) {
            this._id = _id;
        }

        public void setCreatedAt(String createdAt) {
            this.createdAt = createdAt;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }

        public void setPublishedAt(String publishedAt) {
            this.publishedAt = publishedAt;
        }

        public void setSource(String source) {
            this.source = source;
        }

        public void setType(String type) {
            this.type = type;
        }

        public void setUrl(String url) {
            this.url = url;
        }

        public void setUsed(boolean used) {
            this.used = used;
        }

        public void setWho(String who) {
            this.who = who;
        }

        public void setImages(List<String> images) {
            this.images = images;
        }

        public String get_id() {
            return _id;
        }

        public String getCreatedAt() {
            return createdAt;
        }

        public String getDesc() {
            return desc;
        }

        public String getPublishedAt() {
            return publishedAt;
        }

        public String getSource() {
            return source;
        }

        public String getType() {
            return type;
        }

        public String getUrl() {
            return url;
        }

        public boolean getUsed() {
            return used;
        }

        public String getWho() {
            return who;
        }

        public List<String> getImages() {
            return images;
        }
    }
}

嗯 它太长了。。kotlin呢,就这么几行

class GankModel {
   
    var error: Boolean = false
    var results: List<ResultsEntity>? = null
    class ResultsEntity(_id: String, createdAt: String, desc: String, publishedAt: String, source: String, type: String, url: String, var used: Boolean, who: String, images: List<String>) : Serializable {
        var _id: String? = _id
        var createdAt: String? = createdAt
        var desc: String? = desc
        var publishedAt: String? = publishedAt
        var source: String? = source
        var type: String? = type
        var url: String? = url
        var who: String? = who
        var images: List<String>? = images
    }
}

他免去了各种繁琐而重复的get set,让人能把精力放在有意义的事情上,另外还有一个很舒服的就是kotlin的可空类型(就是上图中的那个带问号的类型),它的使用免去了大量的Java中为了避免空指针异常的判空If语句,也让人倍感清新。大量的语法糖也就不再举例子了,Kotlin的学习还在路上!(比较尴尬的是,kotlin在和Java交互中有一些坑,在这次作业App的开发中也遇到了一个导致崩溃的可空类型和Java的交互,需要特别注意!)

项目第一次接触的的一些第三方的好用的库

登录模块借助Bmob后端云bmob后端云
,收藏模块为了避免大量数据库的没有意义的增删改查代码,也是使用了Android中比较常用的realm数据库框架realm
,都在Application中做了初始化。


这是我们的Bmobuser实体类
open class User : BmobUser() {
    var age: Int = 0
    //true男、false女
    var gender: Boolean = false
    var intro: String? = null
    var nickname: String? = null
}

下面是为realm封装的一个工具类:

public class DBManager {

    /**
     * 收藏数据,保存到数据库中
     *
     * @param entity
     */
    public static void save(final SaveModel entity) {
        Realm realm = Realm.getDefaultInstance();
        realm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                realm.copyToRealm(entity);
            }
        });
    }

    /**
     * 取消收藏,从数据库中删除
     *
     * @param entity
     */
    public static void cancelSave(final SaveModel entity) {
        Realm realm = Realm.getDefaultInstance();
        realm.beginTransaction();
        SaveModel resultsEntity = realm.where(SaveModel.class).equalTo("_id", entity.get_id()).findFirst();
        resultsEntity.deleteFromRealm();
        realm.commitTransaction();
    }

    /**
     * 获取数据中所搜收藏记录
     *
     * @return
     */
    public static List<SaveModel> getAllData() {
        Realm realm = Realm.getDefaultInstance();
        realm.beginTransaction();
        RealmResults<SaveModel> results = realm.where(SaveModel.class).findAll();
        realm.commitTransaction();
        return results;
    }

    /**
     * 根据主键查询某条记录
     *
     * @return
     */
    public static SaveModel queryModel(String _id) {
        Realm realm = Realm.getDefaultInstance();
        realm.beginTransaction();
        SaveModel result = realm.where(SaveModel.class).equalTo("_id", _id).findFirst();
        realm.commitTransaction();
        return result;
    }
}

项目的细节

都是Android中的一些常见的View的使用,一些简单的网络请求的封装,Handler Recyclerview Fragment Activity等等都可以看我之前发的博客的知识总结,这感觉是很难说完的。
项目的一个难点是美女图片的加载,在那么多图片的情况下,有可能出现out of memory以及加载的卡顿,这方面一个是借助Glide的缓存策略去避免反复加载,另外是RecyclerView的缓存和回收去避免过多图片驻留内存。

由于平时还有各种学业压力,所以完成项目过程中有一段时间是很赶进度的,难免有些代码功能是实现了,但是在代码的整洁性,结构的清晰性上都有一定可以提升的空间(就是有些代码写的比较丑。。),日后会继续努力去完善的,但是最终的作品是完成了,希望能有一个好的成绩~感谢大家的齐心协力!
最后还要感谢github上各个大神的分享,从中汲取了很多知识和开发技巧,这次遇到的一些问题的难点,就借鉴了许多大神的做法,开源真是伟大!

相关文章

  • 软件工程作业的一些说明

    软件工程作业要求写一款APP,安卓的应用开发也一直是自己的兴趣,所以整个作业的完成过程中还是很兴奋的。我们的APP...

  • D27

    软件工程作业小组汇报,(附美图)

  • 第二章 练习与讨论

    1. 软件工程和程序设计大作业的调查

  • D26

    结束本周双学位,明天小组汇报软件工程的作业,加油。

  • 作业说明

    预习手册咱们最后两单元不做强制要求。 平时坚持自主练习的,两天一课的进度还是比较能消化的。 之前差的多的同学,可以...

  • 收获

    今天用墨刀做了界面、交了软件工程的作业、逛了校园、吃了泡芙,开心!

  • 千里之行,始于足下——软件工程课程总结

    程欣+原创作品转载请注明出处+《软件工程(C编码实践篇)》MOOC课程作业 两个多月的软件工程课程就这么结束了,有...

  • 软件工程作业总结

    实验任务 在给定的 Django 框架上进行二次开发, 完善微信抢票平台,使之能支持基本的后台管理与核心抢票业务....

  • 软件工程2018-09-29

    复习 软件工程:工程开发的过程 软件的输出物: 需求分析说明书(100+页) 2.概要设计说明书 3.详细设计文档...

  • 林志玲的声音也受不了

    昨天文章谈到孩子写作业的事情,多数人认为孩子写作业是天经地义的事情,甚至一些家长认为老师布置的作业越多,说明这个老...

网友评论

      本文标题:软件工程作业的一些说明

      本文链接:https://www.haomeiwen.com/subject/gdmkoqtx.html