美文网首页
Android架构模式-MVC

Android架构模式-MVC

作者: 烧伤的火柴 | 来源:发表于2020-04-16 17:34 被阅读0次

    介绍

    Android项目中,尤其是在比较大的项目开发中,模块内的高聚合和模块间的低耦合性显得尤为重要。所以我们一般情况需要为项目设计一种框架模式,通常情况下我们一般用到的三种模式是MVC、MVP、MVVM。通过框架模式设计的项目能够极大的提高开发效率,提高项目的可维护性和扩展性,另外在模块测试和定位问题上也提供了较大的便利。
    本篇主要介绍MVC
    M-Model 业务逻辑层;V-View视图层;C-Controller 控制层


    mvc示意图.jpg

    三者的关系是:user触发事件的时候,View层发送指令到Controller层,接着Controller层通知Model处理逻辑更新数据,
    Model层更新完数据直接展示到View层上。
    传统的Android开发中,静态布局文件XXX.xml作为View层,各种的JavaBean和Repository 数据库操作 网络层等等都是
    Model层,那么Activity就是Controller层。

    实战

    本次实现使用Kotlin实现
    activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
    
            <Button
                android:id="@+id/queryBt"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Query" />
    
            <Button
                android:id="@+id/insertBt"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Insert" />
        </LinearLayout>
    
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <androidx.core.widget.ContentLoadingProgressBar
                android:id="@+id/progressBar"
                android:layout_width="48dp"
                android:layout_height="48dp"
                style="?android:attr/progressBarStyleLarge"
                android:visibility="gone"
                android:layout_gravity="center" />
    
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/userRv"
                android:visibility="invisible"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </FrameLayout>
    </LinearLayout>
    

    数据模型类Student是一个数据类(data class)

    data class Student(val name: String, val age: Int, val score: Int) {
        companion object {
            fun mockData(): MutableList<Student> {
                val list = MutableList<Student>(10){
                    Student("jawe$it", 30 + it, 60 + it * 2)
                }
    
                return list
            }
        }
    }
    

    StudentManager是一个model类, 管理Student的信息

    class StudentManager private constructor(context:Context) {
        private val key = "key_student"
        private val sharePreference:SharedPreferences = context.getSharedPreferences("students",Context.MODE_PRIVATE)
    
        companion object{
            private var instance:StudentManager? = null
            fun getInstance(context: Context):StudentManager{
                if (instance == null) {
                    instance = StudentManager(context)
                }
                return instance!!
            }
        }
    
        fun saveStudents(students:List<Student>){
            val gsonData = GsonBuilder().create().toJson(students)
            val editor = sharePreference.edit()
            editor?.putString(key, gsonData)?.apply()
        }
    
        fun fetchStudent():List<Student>{
            val gson = Gson()
            val data = sharePreference.getString(key,null)
            var list:List<Student> = listOf()
            data?.let {
                val resultType = object:TypeToken<List<Student>>(){}.type
                list = gson.fromJson(it, resultType)
            }
            return list
        }
    }
    

    为了能够展示Student列表还需要一个Adapter

    class StudentAdapter(dataList: MutableList<Student>) :
        RecyclerView.Adapter<StudentAdapter.StudentViewHolder>() {
        val studentList = dataList
    
        class StudentViewHolder(v: View) : RecyclerView.ViewHolder(v) {
            val nameTv = v.findViewById<TextView>(R.id.nameTv)
            val ageTv = v.findViewById<TextView>(R.id.ageTv)
            val scoreTv = v.findViewById<TextView>(R.id.scoreTv)
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StudentViewHolder {
            val view = LayoutInflater.from(parent.context).inflate(R.layout.item_student, parent, false)
            return StudentViewHolder(view)
        }
    
        override fun getItemCount(): Int = studentList.size
    
        override fun onBindViewHolder(holder: StudentViewHolder, position: Int) {
            val student = studentList[position]
            holder.nameTv.text = student.name
            val age = "年龄是:${student.age}"
            holder.ageTv.text = age
            holder.scoreTv.text = "成绩是:${student.score}"
        }
    }
    

    item_student的布局文件是

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        xmlns:tools="http://schemas.android.com/tools"
        android:orientation="vertical">
    
        <TextView
            android:id="@+id/nameTv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            tools:text="jawe"/>
    
        <TextView
            android:id="@+id/ageTv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            tools:text="27"/>
    
        <TextView
            android:id="@+id/scoreTv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            tools:text="66"/>
    </LinearLayout>
    

    最重要的Controller的工作都是在MainActivity中完成的

    class MainActivity : AppCompatActivity() {
        var queryBt: Button? = null
        var insertBt: Button? = null
    
        var progressBar: ContentLoadingProgressBar? = null
        var userRv: RecyclerView? = null
        val studentManager by lazy {
            StudentManager.getInstance(this)
        }
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            queryBt = findViewById(R.id.queryBt)
            insertBt = findViewById(R.id.insertBt)
            progressBar = findViewById(R.id.progressBar)
            userRv = findViewById(R.id.userRv)
            val layoutManager = LinearLayoutManager(this)
            userRv?.layoutManager = layoutManager
    
            initListener()
    
        }
    
        private fun initListener(){
            queryBt?.setOnClickListener {
                //显示进度条
                showLoading()
    
                thread {
                    var fetchStudents = studentManager.fetchStudent()
                    if (fetchStudents.isEmpty()) {
                        fetchStudents = Student.mockData().toList()
                    }
                    //模拟耗时操作
                    SystemClock.sleep(1000)
                    runOnUiThread {
                        hideLoading()
                        val adapter = StudentAdapter(fetchStudents.toMutableList())
                        userRv?.adapter = adapter
                    }
    
                }
            }
    
            insertBt?.setOnClickListener {
                toast(this, "保存中...")
                thread {
                    studentManager.saveStudents(Student.mockData())
                    //模拟耗时操作
                    SystemClock.sleep(1000)
                    runOnUiThread{
                        toast(this, "保存成功")
                    }
                }
    
            }
        }
    
        private fun showLoading(){
            progressBar?.show()
            progressBar?.visibility = View.VISIBLE
            userRv?.visibility = View.GONE
        }
    
        private fun hideLoading(){
            progressBar?.hide()
    
            progressBar?.visibility = View.GONE
            userRv?.visibility = View.VISIBLE
        }
    }
    

    总结

    通过该列子我们会发现,Activity在充当Controller的角色的时候,内部更多的是处理View的逻辑,比如showLoading和hideLoading函数。而且这里的加载数据和保存数据都需要子线程中保存,处理不当会造成内存泄漏(Activity对象无法被回收掉)

    所以这种模式的缺点是 :
    1.View层的控制能力太弱了,如果要更改图片的颜色,隐藏/显示一个view控件,这些ui视图逻辑都要放到Activity中,这样就
    会造成Activity不仅是Controller层,同时还担任了View的任务忙,这违反软件设计的单一职责。
    2.View层和Model层是紧耦合的,这样代码的毫无扩展性和复用性,而且单元测试和后期维护成本都比较大
    3.Activity充当Controller层,那么一些耗时的操作就要在这里边处理,耗时任务处理不当就会造成内存泄漏,最终导致内存
    溢出。

    相关文章

      网友评论

          本文标题:Android架构模式-MVC

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