Android官方MVVM架構實現組件化之整體結構

來源:互聯網
上載者:User

標籤:tcl   com   fragment   設定   mon   type   src   持久   sqli   

一、google官方MVVM架構講解

我前面對比了MVC和MVP《兩張圖看懂Android開發中MVC與MVP的區別》,可以相對於MVC我們的MVP是有多優越,但是Android開發現在已經開始流行了MVVM,前不久google官方發布了MVVM的正式庫。官方的正式MVVM庫主要包括下面四個:

其中只有ViewModel是MVVM結構中的一個組件,其他的三個都是輔助性質的。

lifecycles 就是處理UI介面的生命週期,在26版本以後的Support庫中,AppCompatActivity和SupportActivity中都實現了LifecycleOwner,內部已經對UI介面的生命週期做了處理了。

LiveData是一個抽象類別,我們可以存放UI頁面需要的資料,就是把資料封裝在LiveData中了,我們可以觀測LiveData中的資料變化,但是LiveData是跟UI的生命週期關聯的,當UI頁面銷毀了,LiveData的資料變化回調是不會執行的。

Room 就是一個sqlite資料持久化庫,我們也可以使用別的ORM庫。

二、MVVM架構優勢

《兩張圖看懂Android開發中MVC與MVP的區別》 前面兩張圖真是了MVC和MVP的區別,我這裡也來一張圖看看MVVM:

看Model和View是不會發生關係的,ViewModel是把View和Model關聯起來的加工廠:

MVVM優勢總結:

1,View和Model雙向繫結,一方的改變都會影響另一方,開發人員不用再去手動修改UI的資料。額,互相自動的。

2,不需要findViewById也不需要butterknife,不需要拿到具體的View去設定資料繫結監聽器等等,這些都可以用DataBinding完成。是不是很舒服?

3,View和Model的雙向繫結是支援生命週期檢測的,不會擔心頁面銷毀了還有回調發生,這個由lifeCycle完成。

4,不會像MVC一樣導致Activity中代碼量巨大,也不會像MVP一樣出現大量的View和Presenter介面。項目結構更加低耦合。

5,更低的耦合把各個模組分開開發,分開測試,可以分給不同的開發人員來完成。

三、MVVM組件化樣本項目架構分析

是項目模組和工程之間的依賴關係:

是工程Android Studio中的目錄結構:

3.1 各模組和彼此之間的關係解釋:

lib_opensource :第三方build.gradle依賴,本項目主要有support、lifecycle、room、fresco、retrofit、okhttp、RxJava、ARouter這些。

libcoremodel: 存放MVVM中的Model和ViewModel兩個模組,就是資料的處理和資料與UI頁面的綁定。依賴libopensource庫。

libcommon : 公用庫,主要有各種base,各種ui組件,自訂群組件,公用的Activity、公用的Fragment,和公用的utils等等。依賴libcoremodel庫。

module_girls : 妹子功能模組,可以在library和application之間切換,自己可以是一個app也可以成為別的app的一個組件模組。組件化編譯時間為app,反之為module。

module_news : 新聞功能模組,可以在library和application之間切換,自己可以是一個app也可以成為別的app的一個組件模組。組件化編譯時間為app,反之為module。

appuniversal : 定製版本的app,組件化編譯時間 modulegirls和modulenews為app,所以不能把這兩個作為module加進來編譯,所以組件化編譯時間appuniversal要依賴libcommon庫,反之就可以把 modulegirls和module_news作為module加進來編譯。

appspecific : 定製版本的app,組件化編譯時間 modulegirls和modulenews為app,所以不能把這兩個作為module加進來編譯,所以組件化編譯時間appspecific要依賴libcommon庫,反之就可以把 modulegirls和module_news作為module加進來編譯。

3.2 ARouter串聯各個模組

使用ARouter來跳轉Activity和擷取Fragment,記得看之前別人的組件化結構文章,一直都在糾結Fragment的擷取問題,我想說的是有了ARouter來擷取Fragment不是超級簡單嗎?

ARouter典型應用

從外部URL映射到內部頁面,以及參數傳遞與解析
跨模組頁面跳轉,模組間解耦
攔截跳轉過程,處理登陸、埋點等邏輯
跨模組API調用,通過控制反轉來做組件解耦
3.3 組件化編譯和非組件化編譯切換

我們在工程根目錄下的gradle.properties檔案中加入一個Boolean類型的變數,通過修改這個變數來識別編譯模式:

每次更改“isModule”的值後,需要點擊 "Sync Project" 按鈕isModule是“整合開發模式”和“組件開發模式”的切換開關

isModule=false
然後在 modulegirls和modulenews中的build.gradle檔案中支援切換:

if (isModule.toBoolean()) {
//組件化編譯時間為application
apply plugin: ‘com.android.application‘
} else {
//非組件化編譯時間為library
apply plugin: ‘com.android.library‘
}

android {
compileSdkVersion build_versions.target_sdk
buildToolsVersion build_versions.build_tools

defaultConfig {    minSdkVersion build_versions.min_sdk    targetSdkVersion build_versions.target_sdk    versionCode 1    versionName "1.0"    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"    //ARouter    javaCompileOptions {        annotationProcessorOptions {            arguments = [moduleName: project.getName()]        }    }}buildTypes {    release {        minifyEnabled false        proguardFiles getDefaultProguardFile(‘proguard-android.txt‘), ‘proguard-rules.pro‘    }}dataBinding {    enabled = true}lintOptions {    abortOnError false}sourceSets {    main {        if (isModule.toBoolean()) {            //組件化編譯時間為app,在對應的AndroidManifest檔案中需要寫ndroid.intent.action.MAIN入口Activity            manifest.srcFile ‘src/main/module/AndroidManifest.xml‘        } else {            manifest.srcFile ‘src/main/AndroidManifest.xml‘            //整合開發模式下排除debug檔案夾中的所有Java檔案            java {                //debug檔案夾中放的是Application類,非組件化時不用有此類                exclude ‘debug/**‘            }        }    }}

}

dependencies {
implementation fileTree(dir: ‘libs‘, include: [‘*.jar‘])
api project(‘:lib_coremodel‘)
api project(‘:lib_common‘)
implementation ‘com.android.support:support-v4:26.1.0‘
annotationProcessor deps.arouter.compiler
}
上面看到了組件化和非組件化編譯會有不用的AndroidManifest檔案,組件化時需要debug檔案夾下面的application類,非組件化時排除此檔案夾。

module下的AndroidManifest檔案是組件化app編譯時間的,寫了MAIN入口Activity

dubug下是組件化app編譯時間的Application類,初始化作為一個app運行時需要的資源等等。在非組件化編譯在build.gradle檔案中排除debug檔案夾的所以東西。

3.4 最後預告:

後面會有一些列介紹在MVVM組件化過程中使用ARouter來跳轉Activity和擷取Fragment、DataBinding實現資料和UI的互相綁定、Rxjava2和Retrofit2動態資料擷取,和AndroidViewModel的封裝。

下面貼貼一個lib_coremodel庫中我封裝的AndroidViewModel,用泛型來確定資料類型,並且是動態URL擷取資料:

package google.architecture.coremodel.viewmodel;

import android.app.Application;
import android.arch.lifecycle.AndroidViewModel;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.databinding.ObservableField;
import android.support.annotation.NonNull;

import java.io.IOException;
import java.lang.reflect.ParameterizedType;

import google.architecture.coremodel.datamodel.http.ApiClient;
import google.architecture.coremodel.datamodel.http.ApiConstants;
import google.architecture.coremodel.datamodel.http.service.DynamicApiService;
import google.architecture.coremodel.util.JsonUtil;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;

/**

  • Created by dxx on 2017/11/20.
    */

public class BaseViewModel<T> extends AndroidViewModel {

//生命週期觀察的資料private MutableLiveData<T>  liveObservableData = new MutableLiveData<>();//UI使用可觀察的資料 ObservableField是一個封裝類public ObservableField<T> uiObservableData = new ObservableField<>();private final CompositeDisposable mDisposable = new CompositeDisposable();private static final MutableLiveData ABSENT = new MutableLiveData();{    //noinspection unchecked    ABSENT.setValue(null);}public BaseViewModel(@NonNull Application application, String fullUrl) {    super(application);    ApiClient.initService(ApiConstants.GankHost, DynamicApiService.class).getDynamicData(fullUrl).subscribeOn(Schedulers.io())            .observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<ResponseBody>() {        @Override        public void onSubscribe(Disposable d) {            mDisposable.add(d);        }        @Override        public void onNext(ResponseBody value) {           if(null != value){               try {                   liveObservableData.setValue(JsonUtil.Str2JsonBean(value.string(), getTClass()));               } catch (IOException e) {                   e.printStackTrace();               }           }        }        @Override        public void onError(Throwable e) {        }        @Override        public void onComplete() {        }    });}/** * LiveData支援了lifecycle生命週期檢測 * @return */public LiveData<T> getLiveObservableData() {    return liveObservableData;}/** * 當主動改變資料時重新設定被觀察的資料 * @param product */public void setUiObservableData(T product) {    this.uiObservableData.set(product);}public Class<T> getTClass(){    Class<T> tClass = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];    return tClass;}@Overrideprotected void onCleared() {    super.onCleared();    mDisposable.clear();}

}

Android官方MVVM架構實現組件化之整體結構

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.