AndroidX設計架構MVVM之DataBinding+ViewModel+LiveData

AndroidX設計架構MVVM之DataBinding+ViewModel+LiveData

原文

AndroidX設計架構MVVM之ViewModel創建流程原理分析
AndroidX設計架構MVVM之ViewModel生命週期分析
AndroidX設計架構MVVM之LiveDatal生命週期及數據監聽分析
AndroidX設計架構MVVM之DataBinding搭配LiveData的分析
AndroidX設計架構MVVM之DataBinding+ViewModel+LiveData

環境各版本:
android studio 3.5.1
android gradle plugin version 3.5.1
gradle version 5.4.1
ViewModel 2.1.0
LiveData 2.1.0

整體來說MVVM架構的搭建依賴於Android的現有的組件,搭建還是非常簡單的,個人覺得最好還是要了解各組件的原理(可參考上邊鏈接),提供的Demo非常簡單,通過組件化實現,可參考組件化Demo-design-component中modulemvvm

相對於單獨使用DataBinding處理業務邏輯來說ObservableField不具備生命週期感知

簡單說下爲什麼要用ViewModel?
ViewModel的生命週期比Activity的生命週期長,當屏幕旋轉時不隨activity的銷燬重建而清除。但是注意ViewModel不是onSaveInstanceState 的替代品,比如當內存不足時,ViewModel隨Activity銷燬,但onSaveInstanceState 依舊可以執行保存重要數據。

簡單說下爲什麼要用LiveData?
LiveData會記錄value的version,並且在inActive狀態時,只記錄value,不通知觀察者更新數據,由inActive狀態切換到active狀態才通知觀察者更新。

在這裏插入圖片描述

1:啓用databinding

android {
    。。。。。。
    //開啓DataBinding
    dataBinding {
        enabled true
    }
 }

2: 導入需要的組件ViewModel 和 LiveData

在項目的build.gradle中加入如下倉庫

allprojects {
    repositories {
        google()
        jcenter()
    }
}

加入具體組件詳細見註釋,可以根據需要選擇

dependencies {
    //使用的版本
    def lifecycle_version = "2.1.0"

    // ViewModel and LiveData
    implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
    // alternatively - just ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version" // For Kotlin use lifecycle-viewmodel-ktx
    // alternatively - just LiveData
    implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
    // alternatively - Lifecycles only (no ViewModel or LiveData). Some UI
    //     AndroidX libraries use this lightweight import for Lifecycle
    implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"

    annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version" // For Kotlin use kapt instead of annotationProcessor
    // alternately - if using Java8, use the following instead of lifecycle-compiler
    implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"

    // optional - ReactiveStreams support for LiveData
    implementation "androidx.lifecycle:lifecycle-reactivestreams:$lifecycle_version" // For Kotlin use lifecycle-reactivestreams-ktx

    // optional - Test helpers for LiveData
    testImplementation "androidx.arch.core:core-testing:$lifecycle_version"
}

3:寫自己的代碼,wtf

用戶UserBean

public class UserBean {
    private String name;
    private String age;

    private UserBean() {

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    public static final class UserBeanBuilder {
        private String name;
        private String age;

        private UserBeanBuilder() {
        }

        public static UserBeanBuilder newBuilder() {
            return new UserBeanBuilder();
        }

        public UserBeanBuilder setName(String name) {
            this.name = name;
            return this;
        }

        public UserBeanBuilder setAge(String age) {
            this.age = age;
            return this;
        }

        public UserBean build() {
            UserBean userBean = new UserBean();
            userBean.age = this.age;
            userBean.name = this.name;
            return userBean;
        }
    }
}

用戶的ViewModel

public class VMUser extends BaseViewModel {
    //live data
    private MutableLiveData<UserBean> mUserInfo;

    public VMUser(@NonNull Application application) {
        super(application);
        mUserInfo = new MutableLiveData<>();
    }

    public MutableLiveData<UserBean> getUserInfo() {
        return mUserInfo;
    }

    public void loadUserInfo() {
        //模擬網絡加載
        MainLooper.getInstance().postDelayed(new Runnable() {
            @Override
            public void run() {
                mUserInfo.setValue(UserBean.UserBeanBuilder.newBuilder().setName("我是live data").setAge("12").build());
            }
        }, 500);
    }

   public void getWeatherInfo(String city) {
        MvvmNetWork.getInstance().getWeatherInfo(city)
                .compose(RxjavaUtils.<BaseEntity<Weather>>io2main())
                .as(this.<BaseEntity<Weather>>bindLifecycle())
                .subscribe(new BaseObserver<Weather>() {
                    @Override
                    public void onSuccess(BaseEntity<Weather> data) {

                    }

                    @Override
                    public void onFailure(int code, Throwable throwable) {

                    }
                });
    }
}

展示用戶信息的View:主要包含基類和具體的子類

//各View的父類
public abstract class AbstractBaseMvvmActivity<V extends ViewDataBinding, VM extends BaseViewModel> extends AppCompatActivity {
    protected V mBinding;
    protected VM mViewModel;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this, getContentViewId());
        if (getVmClass() == null) {
            LogUtils.e("getVmClass() == null");
        } else {
            mViewModel = ViewModelProviders.of(this).get(getVmClass());
            //防止Rxjava使用時的內存泄漏
            getLifecycle().addObserver(mViewModel);
        }
        //爲livedata添加生命週期
        mBinding.setLifecycleOwner(this);
        init();
    }

    protected abstract int getContentViewId();

    protected abstract Class<VM> getVmClass();

    protected abstract void init();

    protected <T> AutoDisposeConverter<T> bindLifecycle() {
        return AutoDisposeUtil.bindLifecycle(this);
    }

    public V getBinding() {
        return mBinding;
    }

    public VM getViewModel() {
        if (mViewModel == null) {
            throw new NullPointerException("mViewModel==null");
        }
        return mViewModel;
    }
}


//展示用戶信息的View
public class MvvmMainActivity extends AbstractBaseMvvmActivity<MvvmActivityMainBinding, VMUser> implements View.OnClickListener {

    @Override
    protected int getContentViewId() {
        return R.layout.mvvm_activity_main;
    }

    @Override
    protected Class<VMUser> getVmClass() {
        return VMUser.class;
    }

    @Override
    protected void init() {
     
        getViewModel().getUserInfo().setValue(UserBean.UserBeanBuilder.newBuilder().setName("live data init").setAge("0").build());
        //設置綁定數據
        getBinding().setVMUser(getViewModel());


        //添加點擊事件
        getBinding().setEventListener(this);

//        //live data 的數據監聽
//        getViewModel().getUserInfo().observe(this, new Observer<UserBean>() {
//            @Override
//            public void onChanged(UserBean userBean) {
//                Toast.makeText(MvvmMainActivity.this, userBean.getName(), Toast.LENGTH_SHORT).show();
//            }
//        });
    }
    
    @Override
    public void onClick(View view) {
        LogUtils.e("haaoaha");
        if (view.getId() == R.id.title) {
           //點擊加載用戶數據
            getViewModel().loadUserInfo();
        }
    }
}

數據動態綁定的 mvvm_activity_main.xml

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

    <data>

        <variable
            name="userNoLive"
            type="com.lyldding.modulemvvm.bean.UserNoLiveBean" />
     <!--用戶數據綁定-->
        <variable
            name="vMUser"
            type="com.lyldding.modulemvvm.viewmodel.VMUser" />
    <!--點擊事件綁定-->
        <variable
            name="eventListener"
            type="com.lyldding.modulemvvm.MvvmMainActivity" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/title"
            style="@style/Text_Style"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{eventListener::onClick}"
            android:text="獲取用戶信息"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
        <!-- data binding 示例-->
        <TextView
            android:id="@+id/name_no_live"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="50dp"
            android:text="@{userNoLive.name}"
            app:layout_constraintBottom_toTopOf="@id/age_no_live"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />


        <TextView
            android:id="@+id/age_no_live"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="50dp"
            android:text="@{userNoLive.age}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintBottom_toTopOf="@id/title" />


        <!--live data 示例-->
        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="@{vMUser.userInfo.name}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/title" />

        <TextView
            android:id="@+id/age"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:text="@{vMUser.userInfo.age}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/name" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章