Android(Kotlin版本)MVC框架的实例以及代码

拥有回忆 提交于 2021-01-07 14:44:07

Android(Kotlin版本)MVC框架的实例以及代码

  本文地址:https://blog.csdn.net/qq_40785165/article/details/112135944,转载需附上此地址
  代码也许是枯燥的,但是创造永远能让人心血澎湃,这大概就是热情吧!
  大家好,我是小黑,一个还没秃头的程序员~~~
  近日较忙,但是也不能忘记了写文章的初心,就是为了记录自己一段时间内的学习以及改变,今日内容为Android开发中MVC的框架设计,由于最近在学习kotlin,所以本文章将使用kotlin作为开发语言,先来看看效果图
MvcDemo动态图
  Demo中的功能很简单,就是个模拟登录的过程,以及登录成功后调用数据接口开发列表,由于想把MVC架构与数据请求一起写了,又想节约篇幅,所以登录模块的代码就不贴出来了,这里只展示列表的设计代码,想要其他代码的同学可以到Demo的github地址手动下载,话不多说,下面开始正文。
  MVC框架由一下三个部分组成:Model|(模型层)、View(视图层)、Controller(控制层)
1.Model:负责请求接口,进行数据处理,将结果通过回调告知Controller层并进行视图更新。
2.View:视图设计,在这里一般指layout中的xml视图代码
3.Controller:控制层,通常指Activity/Fragment,持有Model对象,通过监听Model状态改变进行UI的更新
项目结构如图所示:










(一)先设计视图xml文件即View层,activity_wechat_official_account.xml代码如下:

<?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="match_parent"
    android:orientation="vertical">

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

  列表子项item_office_account.xml代码如下:

<?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"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="match_parent"
        android:layout_height="40dp" />
</LinearLayout>

(二)、设计Activity代码,即Controller层,WeChatOfficialAccountListActivity.kt代码如下:

class WeChatOfficialAccountListActivity : AppCompatActivity(), WeChatOfficeAccountListener {
    private val mList: MutableList<OfficeAccountBean> = ArrayList()
    private val weChatOfficeAccountModel by lazy {
        WeChatOfficeAccountModel()
    }
    private val weChatOfficialAccountAdapter by lazy {
        WeChatOfficialAccountAdapter(this, mList)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_wechat_official_account)
        rv_list.layoutManager = LinearLayoutManager(this)
        rv_list.adapter = weChatOfficialAccountAdapter
        weChatOfficeAccountModel.loadData(this)
    }

    override fun onLoading() {
        Toast.makeText(this, "正在加载中", Toast.LENGTH_SHORT).show()
    }

    override fun onLoadSuccess(list: MutableList<OfficeAccountBean>?) {
        runOnUiThread(Thread {
            Toast.makeText(this, "加载成功", Toast.LENGTH_SHORT).show()
            if (list != null && list.size > 0) {
                mList.addAll(list)
            }
            weChatOfficialAccountAdapter.notifyDataSetChanged()
        })


    }

    override fun onLoadFail(msg: String?) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
    }
}

  从代码中可以得知,Controller层持有了一个Model对象,并实现了一个接口,实现了其中的回调,通过回调进行主线程的UI更新,列表的子项适配器WeChatOfficialAccountAdapter.kt代码如下:

class WeChatOfficialAccountAdapter(var context: Context, var list: MutableList<OfficeAccountBean>) :
    RecyclerView.Adapter<WeChatOfficialAccountAdapter.ViewHolder>() {
    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        var tvName: TextView = view.findViewById(R.id.tv_name)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            LayoutInflater.from(parent.context).inflate(
                R.layout.item_office_account,
                null,
                false
            )
        )
    }

    override fun getItemCount(): Int {
        return list.size
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.tvName.text = list[position].name
    }
}

  回调的接口WeChatOfficeAccountListener.kt代码如下:

interface WeChatOfficeAccountListener {
    fun onLoading()
    fun onLoadSuccess(list: MutableList<OfficeAccountBean>? = null)
    fun onLoadFail(msg: String? = "")
}

(三)、设计Model层,实现数据处理,调用接口等操作,并通过回调通知控制层更新UI,WeChatOfficeAccountModel.kt代码如下:

class WeChatOfficeAccountModel {
    private val weChatOfficeAccountApi by lazy {
        WeChatOfficeAccountApi()
    }

    fun loadData(callback: WeChatOfficeAccountListener) {
        weChatOfficeAccountApi.loadData(callback)
    }
}

  我的Model层里并没有接口调用、数据处理等操作,那是因为我把调用接口都放到了WeChatOfficeAccountApi.kt文件中,代码如下:

class WeChatOfficeAccountApi {
    private val gson by lazy {
        GsonBuilder().serializeNulls().create()
    }

    fun loadData(callback: WeChatOfficeAccountListener) {
        callback.onLoading()
        //拿到OkhttpClient对象
        var okHttpClient = OkHttpClient()
        //构造request对象,get方式,传入接口地址
        var url = Request.Builder()
            .get()
            .url("https://wanandroid.com/wxarticle/chapters/json")
            .build()
        var newCall = okHttpClient.newCall(url)
        newCall.enqueue(object : Callback {
            override fun onFailure(call: Call?, e: IOException?) {
                callback.onLoadFail()
            }

            override fun onResponse(call: Call?, response: Response?) {
                var string = response?.body()?.string()
                Log.e("Tag", string)
                var result = gson.fromJson<DataResult<MutableList<OfficeAccountBean>>>(
                    string,
                    object : TypeToken<DataResult<MutableList<OfficeAccountBean>>>() {}.type
                )
                Log.e("Tag", result.toString())
                callback.onLoadSuccess(result.data)
            }
        })
    }
}

  上述代码中,如果不喜欢这种写法的也可以直接在Model中调用接口,因人而异,调用的接口是玩Android的开放接口,使用的是okhttp网络请求框架,使用gson解析数据,需要依赖的库有:

    implementation 'com.squareup.okhttp3:okhttp:3.5.0'
    implementation 'com.google.code.gson:gson:2.8.6'

  需要的权限有:

<uses-permission android:name="android.permission.INTERNET" />

  好了,到此为止Android的MVC框架就搭建好了,这是我个人对MVC的了解和实践,有不同意见或者建议的可以在下方评论,我们共同进步,效果图和源代码都在开头!最后,祝大家新年快乐,岁岁欢愉!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!