標籤: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架構實現組件化之整體結構