MVC architecture mode of Android architecture

Time:2021-7-28

preface

Due to the rise of MVP, MVVM and component architecture, the application of MVC architecture in Android becomes less and less, but MVC is the foundation. Only by understanding MVC can we better understand MVP and MVVM, because the latter two are developed based on MVC.

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

For example, an app whose function is relatively simple and will not be extended in the later stage can be written in MVC architecture, and all logic can be written in activity or fragment. If you use MVP architecture, you will need to add many classes accordingly, which may not improve your development efficiency.

MVC mode role description in Android

In Android projects, view in MVC is our XML, and logic is our activity or fragment. Their division of labor is clear. Layout is responsible for UI, activity is responsible for logic, and model is responsible for data processing.

type definition Form of expression
M(Model) Model layer (data storage, logical processing) Model class
V(View) View layer (UI presentation) Layout file, activity
C(Controller) Control layer (logic processing) Activity

MVC example explanation

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

The overall function of this instance is very simple. It uses okhttp to request a URL, then uses gson to parse the data, glide to display the picture, and recyclerview to display the list. The example effect is as follows. The API I use here is fromDry goods concentration campThe API found on is:https://gank.io/api/v2/data/c…

MVC architecture mode of Android architecture

Create entity class

MVC architecture mode of Android architecture
Through the JSON data returned by the interface, we can create an entity class. We can write it manually or generate it directly with tools. If it is in Java language, I recommend using gsonformat. If it is in kotlin language, we can use the jsontoktlinclass plug-in to generate it automatically, because I write it 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 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, that is, the basic usage of recyclerview.

We know that in MVC architecture, activity also plays 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 in the model layer and then transfer the data 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 controller layer

In the Android MVC architecture, the controller layer is an activity or fragment, so we need to perform logical processing in the 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([email protected], msg, Toast.LENGTH_SHORT).show()
            }
        })
    }

}

So far, a complete MVP architecture app has been completed.

Summary

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

The advantage of MVC mode is that it is simple and convenient, but its disadvantages are also obvious. With the increase of interface and logic complexity, the activity will appear very bloated. An activity may have thousands of lines of code, which makes it very difficult to maintain.

In order to solve the problems of the MVC mode mentioned above, the responsibilities of the view layer and the controller layer in the activity are separated, so as to optimize and reduce the amount of activity code. Therefore, the MVP mode appears. We will talk about this mode next time.

Source code

Source codeIt has been uploaded to GitHub. You can get it yourself if necessary.