头图

Preface

Due to the rise of MVP, MVVM, and componentized architecture, the application of MVC architecture in android has become less and less, but MVC is the foundation, and a good understanding of MVC can better understand MVP and MVVM, because the latter two are based on MVC Developed.

Some people think that as long as the app is well-architected, the app will do well. This understanding is actually wrong. The essence of the architecture must serve the business. Each architecture must have its advantages and disadvantages. An architecture that can suit your needs and improve development efficiency is a good architecture.

For example, an App that has relatively simple functions and no longer expands in the later period can be written in the MVC architecture, and all the logic is written in Activity or Fragment. If you use the MVP architecture, you will need to add a lot of classes accordingly. May not improve your development efficiency.

MVC pattern role description in Android

In Android projects, the View in MVC is our XML, and the logic is our Activity or Fragment. Their division of labor is clear. The layout is responsible for the UI, the Activity is responsible for the logic, and the Model is responsible for data processing.

Types ofdefinitionManifestations
M(Model)Model layer (data storage, logic processing)Model class
V(View)View layer (UI display)Layout file, Activity
C(Controller)Control layer (logical processing)Activity

MVC example explanation

I believe that everyone knows the MVC architecture. I won't talk about that much in the theoretical part. We will explain the specific implementation of the MVC architecture through an example.

The overall function of this example is very simple. It uses Okhttp to request a url, then uses Gson to parse the data, Glide displays pictures, and RecyclerView displays the list. The example effects are shown below. The API I use here is from dry goods concentration camp . The API is: https://gank.io/api/v2/data/category/Girl/type/Girl/page/2/count/10

image.png

Create entity class

image.png
Through the Json data returned by the interface, we can create entity classes. We can write them manually or generate them directly with tools. If you use Java language, I recommend using GsonFormat. If you use Kotlin language, use the JsonToKotlinClass plug-in to automatically Generate, because I am writing in Kotlin language, so I use JsonToKotlinClass to automatically generate entity class code, as shown below:

data class DataBean(
        val data: List<Data>,
        val page: Int,
        val page_count: Int,
        val status: Int,
        val total_counts: Int
)

data class Data(
        val _id: String,
        val author: String,
        val category: String,
        val createdAt: String,
        val desc: String,
        val images: List<String>,
        val likeCounts: Int,
        val publishedAt: String,
        val stars: Int,
        val title: String,
        val type: String,
        val url: String,
        val views: Int
)

Create the View layer

The view layer is our layout file, the code is very simple, it is a full-screen RecyclerView, as shown below:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Because we use RecyclerView here, we have to create an adapter for RecyclerView. The code is as follows:

class MvcRecyclerAdapter(private val dataList: List<Data>, private val context: Context) : RecyclerView.Adapter<MvcRecyclerAdapter.ViewHolder>() {

    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val ivImg: ImageView = view.findViewById(R.id.iv_img)
        val tvDesc: TextView = view.findViewById(R.id.tv_desc)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder =
            ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.layout_list_item, parent, false))

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val bean = dataList[position]
        Glide.with(context).load(bean.images[0]).into(holder.ivImg)
        holder.tvDesc.text = bean.desc
    }

    override fun getItemCount() = dataList.size
}

The code of this adapter is not difficult, it is the basic usage of RecyclerView.

We know that in the MVC architecture, Activity also assumes the role of view. Activity needs to initialize the layout. The code is as follows:

class MainActivity : AppCompatActivity() {

    private lateinit var adapter: MvcRecyclerAdapter
    private val mList = ArrayList<Data>()
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initView()
    }

    private fun initView() {
        val layoutManager = LinearLayoutManager(this)
        recyclerView.layoutManager = layoutManager
        recyclerView.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL))
        adapter = MvcRecyclerAdapter(mList, this)
        recyclerView.adapter = adapter
    }

}

Create Model layer

We need to request data at the Model layer, and then pass the data out through the interface. The specific code is as follows:

class OkhttpModel {

    private val url = "https://gank.io/api/v2/data/category/Girl/type/Girl/page/2/count/10"
    private lateinit var listener : OnOkhttpListener

    fun getData(mListener: OnOkhttpListener) {
        listener = mListener
        thread {
            val okHttpClient = OkHttpClient()
            val request = Request.Builder().get().url(url).build()
            okHttpClient.newCall(request).enqueue(object : Callback {
                override fun onFailure(call: Call, e: IOException) {
                    listener.onFail(e.message.toString())
                }

                override fun onResponse(call: Call, response: Response) {
                    val responseData = response.body?.string()
                    responseData?.let {
                        val dataBean = Gson().fromJson(responseData, DataBean::class.java)
                        listener.onSuccess(dataBean)
                    }

                }

            })
        }

    }

    interface OnOkhttpListener {
        fun onSuccess(bean: DataBean)
        fun onFail(msg: String)
    }
}

Create the Controller layer

The Controller layer in the Android MVC architecture is Activity or Fragment, so we need to perform logical processing in Activity, the code is as follows:

class MainActivity : AppCompatActivity() {

    private lateinit var adapter: MvcRecyclerAdapter
    private var mList = ArrayList<Data>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initView()
    }

    private fun initView() {
        val layoutManager = LinearLayoutManager(this)
        recyclerView.layoutManager = layoutManager
        recyclerView.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL))
        adapter = MvcRecyclerAdapter(mList, this)
        recyclerView.adapter = adapter

        loadData()
    }

    private fun loadData() {
        val model = OkhttpModel()

        model.getData(object : OkhttpModel.OnOkhttpListener {
            override fun onSuccess(bean: DataBean) {
                bean.data.forEach {
                    mList.add(it)
                }
                runOnUiThread {
                    adapter.notifyDataSetChanged()
                }
            }

            override fun onFail(msg: String) {
                Toast.makeText(this@MainActivity, msg, Toast.LENGTH_SHORT).show()
            }
        })
    }

}

So far, a complete MVP architecture App is finished.

summary

The architecture is always to serve the business. Don’t design for design, otherwise it will reduce development efficiency. For example, there are only a few files in an App and no architecture is required. In fact, the above example can completely put the code requesting network data in In Activity, so we don't need the Model layer. I added the Model layer above just to demonstrate the writing of the MVC architecture pattern.

The advantage of the MVC pattern is simplicity and convenience, but its disadvantages are also obvious. As the interface increases and the logic complexity increases, the Activity will appear very bloated. An Activity may have thousands of lines of code, making it quite difficult to maintain.

In order to solve the problems of the above-mentioned MVC mode, separate the responsibilities of the View layer and the Controller layer in the Activity, thereby optimizing and slimming the Activity code volume, so the MVP mode appears, which we will talk about next time.

Source code

source code has been uploaded to github, and you can pick it up if you need it.


Maenj_Ba_lah
28 声望7 粉丝

真正的大师,永远怀着一颗学徒的心。