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 understanding MVC is the best way to understand MVP, MVVM, because the latter two are based on MVC development.
Some people think that as long as the architecture is good, the APP is good, this kind of understanding is actually wrong, the essence of the architecture must be to 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 with relatively simple functions and no longer expands in the later stage can be written with MVC architecture, and all logic is written in activities or fragments. If you use MVP architecture, you will correspondingly add many classes, which may not improve your development efficiency.
Description of the role of MVC pattern in Android
In Android projects, View in MVC is our XML, while logic is our class such as 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 | define | form |
---|---|---|
M(Model) | Model layer (data storage, logic processing) | Model class |
V(View) | View layer (UI presentation) | Layout files, activities |
C(Controller) | Control layer (logical processing) | Activity |
MVC example
I’m sure you all know the MVC architecture, and I’m not going to go into the theoretical part, but I’m going to show you an example of how the MVC architecture is implemented.
RecyclerView/RecyclerView/RecyclerView/RecyclerView/RecyclerView/RecyclerView/RecyclerView/RecyclerView/RecyclerView/RecyclerView/RecyclerView/RecyclerView/RecyclerView/RecyclerView/RecyclerView https://gank.io/api/v2/data/c…
Create Entity Class
From the JSON data returned by the interface, we can create an entity class, either manually or directly by using a tool. If using Java, I recommend using GsonFormat. If using Kotlin, we can use the JsonTokotlinClass plugin to automatically generate the entity class. Since I wrote it in Kotlin, I used JSONTOKotlinClass to automatically generate the 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 a View layer
The RecyclerView layer is our layout file. The code is very simple. It is a full screen RecyclerView, like this:
<? The 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>
We need to create a RecyclerView adapter. We need to create a RecyclerView adapter as shown in this code:
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 adapter code is not difficult, is the basic use of RecyclerView.
We know that in the MVC architecture, the Activity also acts as a view. The 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 a Model layer
We need to request the data in the Model layer, and then pass the data through the interface 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
In Android MVC architecture, the Controller layer is Activity or Fragment, so we need to conduct 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()
}
})
}
}
At this point, a complete MVP architecture of the App is done.
summary
Architecture is always to serve the business, do not design for the sake of design, otherwise it will reduce the development efficiency, for example, an App only has a few files, do not need the architecture, in fact, the above example can completely put the code requesting network data into the Activity, so we do not need the Model layer. I added the Model layer above just to demonstrate how the MVC architectural pattern is written.
The advantage of the MVC pattern is that it is simple and convenient, but its disadvantage is equally obvious. As the number of interfaces increases and the logic complexity increases, the Activity can become very bloated. An Activity may have thousands of lines of code, which makes it difficult to maintain.
In order to solve the problems of the above MVC pattern, 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, so there is the MVP pattern, which we will talk about next time.
The source code
Source code has been uploaded to github, there is a need to fetch.