zoukankan      html  css  js  c++  java
  • 使用DataBinding还在为数据处理头疼?这篇文章帮你解决问题

    前言

    在前几年兴起了MVVM架构设计模式,最具有代表的框架就是DataBinding,虽然这种设计架构非常新颖,但是在使用中仍然还有很多痛点,所以我当时觉得短时间这个设计架构可能不会太流行。

    最近接手了新项目,使用的就是MVVM,才发现只一两年的功夫MVVM的发展竟然这么快,已经是Android开发者必备的技能之一了。

    正文

    DataBinding在刚开始阶段,最令我头疼的就是数据处理的问题,往往为了显示数据,我要在XML中绑定N多个字段,如果是一个中等以上的工程,还有更蛋疼的问题,例如:

    • 你的XML可能迫切的需要if或者switch这样的判断;
    • 意想不到的空指针

    在2018年,Google推出JetPack库,其中的ViewModel+LIveData终于把MVVM推上了新的高度。

    ViewModel

    使用ViewModel需要依赖lifecycle库:

    implementation "android.arch.lifecycle:viewmodel:x.x.x"
    implementation "android.arch.lifecycle:extensions:x.x.x"
    
    

    ViewModel的创建方法主要有两种:

    // 获取FragmentActivity共享的ViewModel
    ViewModelProviders.of(FragmentActivity).get(ViewModel::class.java)
    
    // 获取FragmentActivity共享的ViewModel
    ViewModelProviders.of(Fragment).get(ViewModel::class.java)
    
    

    ViewModel的共享范围主要有两种:一种是FragmentActivity,一种是Fragment,可以根据自己的需要选择共享的范围。如果你想要一个Application级别的ViewModel,目前是不支持的,你可以自定义Application持有一个ViewModel,或者使用单例模式。

    ViewModel解决的问题

    1、扩大数据共享的应用场景。

    一般的数据共享是Activity与Fragment的数据传递,传统做法是使用setArguments(Bundle),这种方法有以下弊端:

    • 可能无法预测setArguments会在Fragment的哪个周期完成,要进行异常判断;
    • setArguments中的数据可能会发现改变,如果是Activity直接设置Fragment的数据,耦合性很高;
    • 数据较多时,Fragment会有很多的变量,影响可读性和维护性。

    使用ViewModel,可以避免以上的尴尬情况,需要什么数据就从ViewModel中取:

    • 新加数据传递,不用修改Activity的setArguments代码,Fragment也不用编写数据接收的方法;
    • 减少数据传递,不必考虑是否要删除暂时无用的代码;
    • 取数据时,请注意数据的有效性,做好判断即可;

    除此之外,自定义View也可以得到ViewModel,这样某些功能耦合性非常强的自定义View开发更加便捷。不过需要注意的是View的context的上下文是Activity类型(不会是Fragment)的,所以只能使用Activity级别的数据共享。

    2、解决DataBinding的视图显示问题。

    如果视图的显示需要很多的数据,那么XML就会变得越来越臃肿,并且迫切需要添加一些简单的判断,例如:

    如果A为空就显示B,如果B为空就先是C,如果是C为空...

    虽然DataBinding支持三元运算符,能够满足if判断的需要,但是很显然在XML维护逻辑要比Java或者Kotlin要困难的多(无拼写错误提示等)。所以我们非常需要把部分代码从XML分离出来,ViewModel就非常适合担任这个角色。

    修改前:

    <?xml version="1.0" encoding="utf-8"?>
    <layout>
    
        <data>
    
            <variable
                    name="A"
                    type="String" />
    
            <variable
                    name="B"
                    type="String" />
    
            <variable
                    name="C"
                    type="String" />
    
        </data>
    
         <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:maxLines="4"
                    android:ellipsize="middle"
                    android:text="A != null ? A : B != null ? B : C" />
        ...
    
    </layout>
    
    

    修改后:

    <?xml version="1.0" encoding="utf-8"?>
    <layout>
    
        <data>
    
            <variable
                    name="viewModel"
                    type="ViewModel" />
    
        </data>
    
        <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:maxLines="4"
                    android:ellipsize="middle"
                    android:text="@{viewModel.getShowContent()}" />
    ...
    
    </layout>
    
    

    LiveData

    刚才我们已经讨论了ViewModel的用法,但是还有一个问题没有解决,那就是数据更新的问题,解决这个问题的最佳方式就是观察者模式,但是如果没有处理好观察者的注册和解绑很容易出现内存溢出。LiveData就可以完美的解决这个问题。

    我们需要添加LiveData的依赖:

    implementation "androidx.lifecycle:lifecycle-livedata:2.1.0"
    
    

    下面是一个简单的示例:

    // 名为openDrawer的Boolean类型的LiveData
    public final MutableLiveData<Boolean> openDrawer = new MutableLiveData<>();
    
    // 更新openDrawer 
    openDrawer.setValue(true)
    
    // 观察openDrawer 的值的变化
    openDrawer.observe(this, aBoolean -> {
                 Toast.makeText(this, "${aBoolean}", Toast.LENGTH_SHORT).show();
            });
    
    

    LiveData的子类是MutableLiveData,内部有value属性保存最新的值,订阅LiveData的变化,直接调用LiveData.observe():

    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)
    owner:注册的周期,会在owner销毁的时候,解绑观察者。
    observer:观察的值发生变化的回调函数

    owner直接使用Activity或者Fragment即可。如果你还不了解Lifecycle的使用,可以查看一下相关的资料。

    总结

    最后我画了一张架构图,总结了一下最新的MVVM的使用架构:

     
    image

    Activity:处理UI问题,但是应当尽量避免这样做,尽量统一使用DataBinding。
    ViewModel:保存页面需要的数据,功能复杂的话可以拆分成多个。
    DataBinding:处理UI视图,持有ViewModel做数据展示。如果页面功能比较复杂,可以对ViewModel和DataBinding再次细分。

    如果大家对MVVM有更棒的理解,欢迎留言共同学习。

    推荐阅读:

    2017-2020历年字节跳动Android面试真题解析(累计下载1082万次,持续更新中)

    作者:珠穆朗玛小王子
    链接:https://www.jianshu.com/p/a2eb8e1807ef
    来源:简书

  • 相关阅读:
    关于applet
    Hello.java
    filter用户授权的例子
    logfilter
    Java EE课程设计——企业人力资源管理系统
    条件查询、SQL、JPQL、HQL比较
    web service和ejb的区别
    RPC
    hashcode()和equals()的区别
    关于JSON
  • 原文地址:https://www.cnblogs.com/Android-Alvin/p/12464315.html
Copyright © 2011-2022 走看看