当Jetpack遇上MVVM

   日期:2020-08-28     浏览:92    评论:0    
核心提示:MVVM模式的理解MVVM模式是指Model-View-ViewModel,该模式中的View是将View的状态和行为完全抽象化,把逻辑与界面的控制完全交给ViewModel处理Model 用于获取业务数据模型View 定义了界面中的布局和外观ViewModel 逻辑控制层,负责处理数据和处理View层中的业务逻辑MVVM优缺点优点(1)双向绑定技术,当Model变化时,View也会自动变化。做到数据的一致性(2)View的功能进一步强化,具有控制的部分功能,View可以像控制器一样具有

MVVM模式的理解

MVVM模式是指Model-View-ViewModel,该模式中的View是将View的状态和行为完全抽象化,把逻辑与界面的控制交给ViewModel处理
Model 用于获取业务数据模型
View 定义了界面中的布局和外观
ViewModel 逻辑控制层,负责处理数据和处理View层中的业务逻辑

MVVM优缺点

优点
(1)双向绑定技术,当Model变化时,View也会自动变化,做到数据的一致性
(2)View的功能进一步强化,具有控制的部分功能,由于控制器的功能部分移动到View上处理,从而对控制器进行了瘦身
(3)可以对View或ViewController的数据处理部分抽象出一个函数处理model,这样它们专职页面布局和页面跳转,必然是进一步的简化
缺点
(1)数据绑定使得 Bug 难以调试,当你看到界面异常了,有可能是你 View 的代码有问题,也可能是 Model 的代码有问题
(2)数据双向绑定不利于代码重用,一个View绑定了一个model,不同模块的model不同,那就不能简单重用View了

Model层

package com.example.myapplication

data class QuestionBean(
    val `data`: Data,
    val errcode: String,
    val errorMsg: String
)

data class Data(
    val answerData: AnswerData,
    val hasAnswer: Boolean,
    val options: List<Option>,
    val questionData: QuestionData
)

data class AnswerData(
    val answer: String,
    val id: String,
    val isright: String,
    val optionid: String,
    val point: String,
    val questionid: String,
    val remark: Any,
    val resultid: String
)

data class Option(
    val id: String,
    val title: String
)

data class QuestionData(
    val isbank: String,
    val paperid: String,
    val point: String,
    val questionId: String,
    val questionTypeName: String,
    val questiontype: String,
    val title: String,
    val useTime: String
)

Repository层

这里使用的是RxHttp,github地址:https://github.com/liujingxing/okhttp-RxHttp


class MainRepository {
    fun getData(liveData: MutableLiveData<QuestionBean>) {
        RxHttp.postForm(MainApi.URL)
            .add("questionId", "139")
            .add("resultId", "143")
            .asClass(QuestionBean::class.java)
            .observeOn(AndroidSchedulers.mainThread())//指定回调线程
            .subscribe({ question: QuestionBean? ->
                liveData.value = question
            }) { throwable: Throwable? ->
                Log.d(TAG, throwable?.message.toString())
            }
    }
}

ViewModel层

class QuestionViewModel : ViewModel() {
    private var mainRepository: MainRepository? = null
    private var liveData: MutableLiveData<QuestionBean>? = null

    init {
        mainRepository = MainRepository()
    }

    fun getLiveData(): MutableLiveData<QuestionBean>? {
        if (liveData == null) {
            liveData = MutableLiveData()
        }
        return liveData
    }


    fun getDataFromNetWork() {
        mainRepository?.getData(liveData!!)
    }
}

View层

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable name="test" type="com.example.myapplication.QuestionBean" />
    </data>

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout android:id="@+id/refresh" android:layout_width="match_parent" android:layout_height="match_parent">

        <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity">

            <TextView android:id="@+id/tv" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="@{test.data.questionData.title}" />

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

</layout>

Activity

class MainActivity : AppCompatActivity() {
    private lateinit var activityMainBinding: ActivityMainBinding
    private val viewModel by lazy {
        ViewModelProvider(
            this,
            ViewModelProvider.NewInstanceFactory()
        ).get(QuestionViewModel::class.java)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        val liveData = viewModel.getLiveData()
        initData()
        activityMainBinding.recyclerview.layoutManager =
            LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
        liveData?.observe(this, {
            activityMainBinding.refresh.isRefreshing = false
            activityMainBinding.setVariable(BR.test, it)
            activityMainBinding.recyclerview.adapter = TestAdapter(it.data.options, this)
        })
        activityMainBinding.lifecycleOwner = this
        activityMainBinding.refresh.setOnRefreshListener {
            initData()
        }
    }

    private fun initData() {
        activityMainBinding.refresh.isRefreshing = true
        viewModel.getDataFromNetWork()
    }
}

相应的Adapter

class TestAdapter(val data: List<Option>, val context: Context) :
    RecyclerView.Adapter<TestAdapter.ItemHolder>() {

    class ItemHolder(var viewDataBinding: ViewDataBinding) :
        RecyclerView.ViewHolder(viewDataBinding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemHolder {
        val itemBinding = DataBindingUtil.inflate<ViewDataBinding>(
            LayoutInflater.from(context),
            R.layout.item,
            parent,
            false
        )
        return ItemHolder(itemBinding)
    }

    override fun onBindViewHolder(holder: ItemHolder, position: Int) {
        holder.viewDataBinding.setVariable(BR.options, data[position])
        holder.viewDataBinding.executePendingBindings()
        holder.viewDataBinding.root.setOnClickListener {
            Toast.makeText(context, "点击了第${position}个", Toast.LENGTH_SHORT).show()
        }
    }

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

}

item.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

        <variable name="options" type="com.example.myapplication.Option" />
    </data>

    <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content">

        <TextView text="@{options.title}" android:layout_width="match_parent" android:layout_height="wrap_content" />

    </LinearLayout>
</layout>
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服