什么是Android Jetpack?
Android Jetpack是谷歌在2018年I/O開發者大會上推出的新一代組件、工具和架構指導,旨在加快開發者的 Android 應用開發速度。 ——官方介紹網站
Android Jetpack 組件是庫的集合,這些庫是為協同工作而構建的,不過也可以單獨采用,同時利用 Kotlin 語言功能幫助您提高工作效率。可全部使用,也可混合搭配!
Android Jetpack組件的優勢:
Jetpack推出的主要目的是為了能夠讓開發者更加快速、方便以及高質量的完成產品開發
- 輕松管理應用程序的生命周期,后臺任務的管理,導航的處理等等
- 利用Jetpack組件進行開發可以有效減少內存溢出、崩潰的概率,提升應用開發的質量
Jetpack組件主要分為四個方向:基礎,架構,行為和UI。詳情見下
Android Jetpack組件推薦的使用項目架構
上面架構組件的功能如下:
- Activity和Fragment負責產品與用戶的交互
- ViewModel作為數據的存儲和驅動
- Resposity負責調度數據的獲取(Room儲存本地序列化的數據,Retrofit獲取遠程數據的數據)
ViewModel+ LiveData
ViewModel的優點:
- 解決了運行中斷和界面重建時的數據保存問題 (橫豎屏切換,導致Activity銷毀并重新創建時,ViewMode仍然可以保留之前讀取到的數據不會因為Activity的銷毀而丟失,這樣我們無需額外再浪費資源去再次請求數據)
- 配合LiveData實時獲取最新數據
- 實現Activity中Fragment之間的數據交互(數據共享)
- 數據和界面的分離,使數據驅動界面 (ViewModel類被設計為通過lifecycle感知的方式存儲和管理UI相關數據)
ViewModel的生命周期:
- ViewModel對象的范圍是在獲取ViewModel時傳遞給ViewModelProvider的Lifecycle生命周期
- ViewModel在內存中直到Activity銷毀或Fragment被移除
- 系統首次調用活動對象的onCreate()方法時,通常會請求ViewModel
- 系統可能會在整個活動的整個生命周期中多次調用onCreate(),例如當設備屏幕旋轉時
- ViewModel從第一次請求ViewModel直到活動完成并銷毀時存在
ViewMode在其生命周期的范圍內會一直保存在內存中,所以橫豎屏切換 當切換手機橫豎屏后,Activity會destroy并重新onCreate來重構當前界面,生命周期再次重新觸發onCreate,但是ViewMode 并沒有重新執行獲取數據的操作。
由于 ViewModel 生命周期可能長與 activity 生命周期,所以為了避免內存泄漏 Google 禁止在 ViewModel 中持有 Context 或 activity 或 view 的引用。
如果有些請求數據的情況必須用到Context,在繼承ViewMode的時候,可以改為繼承AndroidViewMode,這個類會返回一個帶有Context的構造函數。
ViewMode執行onCleared操作,這個是ViewMode的一個回調,表明當前Activity要徹底關閉,ViewMode需要做一些回收清理的操作
LiveData
優點:
- 確保UI界面的數據狀態
- 沒有內存泄漏,不會因為Activity的不可見導致Crash
- 一個存放可被觀察的數據持有類,但與一般的被觀察者不同的是,它是有生命周期感知功能,解決了android開發者需要去手動處理生命周期的痛點。
- 共享資源
viewMode.getUserLiveData().observe(this, new Observer<String>() {
@Override
public void onChanged(String users) {
fragment2.setText("fragment2==\n" + users);
}
});
LiveData是一個observable數據持有類,LiveData是生命周期感知的,這意味著它跟隨其他應用程序組件(如activities, fragments, or services)的生命周期。這種感知能力確保LiveData只更新處于活躍生命周期狀態的應用程序組件
LiveData與一個Observer關聯,如果觀察者的生命周期處于STARTED或RESUMED狀態,則表示觀察者處于活動狀態。LiveData只通知活躍的觀察者做更新。注冊到LiveData對象中的不活躍的觀察者則得不到數據更新的通知。
注冊一個observer并與實現了LifecycleOwner接口的對象配對。這種關系允許當相應的Lifecycle對象的狀態改變為DESTROYED時,觀察者被移除
利用ViewMode(配合LiveData實時獲取最新數據)進行Fragment之間的數據交互
public class OneFragment extends BaseFragment {
@BindView(R2.id.fragment2)
TextView fragment2;
@Override
protected int initLayout() {
return R.layout.fragment_detail;
}
@Override
protected void initView(View view) {
//綁定ViewMode的selected的值,當有更新時通知DetailFragment
SharedViewModel viewMode = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
viewMode.getUserLiveData().observe(this, new Observer<String>() {
@Override
public void onChanged(String users) {
fragment2.setText("fragment2==\n" + users);
}
});
}
}
public class TwoFragment extends BaseFragment {
@BindView(R2.id.fragment1)
TextView fragment1;
SharedViewModel viewMode;
@Override
protected void initView(View view) {
//注意:這里ViewModelProviders.of(getActivity())這里的參數需要是Activity,而不能是Fragment,否則收不到監聽
viewMode = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
fragment1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//當點擊某一個item的時候,更新viewmode中的selected的值
viewMode.select("fragment1點擊后,更新viewmode中的值,fragment2 里面的數據同步更新");
}
});
}
@Override
protected void initData() {
viewMode.getUserLiveData().observe(this, new Observer<String>() {
@Override
public void onChanged(String users) {
Log.w("TAG", "====" + users);
}
});
}
@Override
protected int initLayout() {
return R.layout.fragment_master;
}
}
public class SharedViewModel extends AndroidViewModel {
//userLiveData保存的是被選中的item的狀態或者數據
private MutableLiveData<String> userLiveData;
public MutableLiveData<String> getUserLiveData() {
if (userLiveData == null) {
Log.w("TAG", "SharedViewModel-getUserLiveData");
userLiveData = new MutableLiveData<>();
}
return userLiveData;
}
//主要通過masterFragment進行調用交互,用來更新selected中的值
public void select(String item) {
userLiveData.setValue(item);
}
public SharedViewModel(@NonNull Application application) {
super(application);
}
/**
* 這里可以執行一些資源釋放、數據清理的操作
* ViewMode會執行onCleared操作,這個是ViewMode的一個回調,
* 表明當前Activity要徹底關閉,ViewMode需要做一些回收清理的操作,如下代碼:
*/
@Override
protected void onCleared() {
super.onCleared();
}
}
上述代碼的邏輯很簡單,OneFragment與TwoFragment并不直接進行交互,而是各自與ViewMode進行交互,OneFragment用來更新維護ViewMode中的數據,TwoFragment可以收到來自ViewMode中數據更新的通知。這樣便達到了兩個frangment之間的數據通信。
LifeCycles原理
Lifecycles是生命周期管理組件 另一組件的生命周期狀態(隨著Activity和Fragment)的變化而執行動作,support 26 以上的兼容包中的AppCompatActivity與Fragment中默認已實現了LifeCycleOwner接口,保證了LiveData及ViewModel具備了生命周期感知與內存緩存的能力。
場景使用:在平時的開發過程中,我們難免有些邏輯的執行是和UI的生命周期相結合的,需要在特定的生命周期中執行相應的方法,我們平時做的可能就是在View中的每個周期調用Present中獲取數據的方法,然后在調用View的回調接口更新UI,但現在使用Lifecycles可以使用注解和觀察的模式自動調用Observe中定義好的方法。
//誰觀察生命周期 就注冊誰 兩個角色定義好后,需要讓他們之間建立聯系
//獲取Lifecycle
getLifecycle().addObserver(new LocationListener());
public class LocationListener implements LifecycleObserver {
private static final String TAG = "TAG";
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void onActivityCreate(LifecycleOwner owner) {
Log.w(TAG, "onActivityCreate");
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onActivityDestroy(LifecycleOwner owner) {
Log.w(TAG, "onActivityDestroy");
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onActivityPause(LifecycleOwner owner) {
Log.w(TAG, "onActivityPause");
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onActivityResume(LifecycleOwner owner) {
Log.w(TAG, "onActivityResume");
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onActivityStart(LifecycleOwner owner) {
Log.w(TAG, "onActivityStart");
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onActivityStop(LifecycleOwner owner) {
Log.w(TAG, "onActivityStop");
}
}
Lifecycle 原理 如何感知 activity 或 fragment 生命周期
1、activity 和 fragment 已經實現了 LifecycleOwner
2、出現了一個LifecycleRegistry,是 Lifecycle 的一個實現類。通過markState方法在onSaveInstanceState把 Lifecycle 狀態標記為Lifecycle.State.CREATED。
3、onCreate 方法里有個ReportFragment,
4、利用 fragment 的特性,綁定了一個 fragment 然后在其生命周期dispatch()方法中調用了LifecycleRegistry的handleLifecycleEvent,此方法便是通知觀察者的地方。Lifecycle.Event,判斷執行事件后下一個到達的狀態,然后使用moveToState()中修改活動的生命周期
5、通知觀察者addObserver 后,把observer維護到ObserverWithState然后裝到 map 里。
然后通過handleLifecycleEvent方法最終遍歷map 通知 observer。
偽代碼
public class ComponentActivity extends androidx.core.app.ComponentActivity implements LifecycleOwner{
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
@CallSuper
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
mLifecycleRegistry.markState(Lifecycle.State.CREATED);
super.onSaveInstanceState(outState);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSavedStateRegistryController.performRestore(savedInstanceState);
ReportFragment.injectIfNeededIn(this);
if (mContentLayoutId != 0) {
setContentView(mContentLayoutId);
}
}
public void addObserver(@NonNull LifecycleObserver observer) {
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
}
ViewModel 原理
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});
ViewModel 和 onSaveInstaceState方法區別在于:ViewModel只能保存因為配置更改導致重建的數據,但是它能保存大量和復雜的數據;onSaveInstaceState能保存配置更改導致重建和資源限制導致重建的數據,但是它只能保存少量簡單的數據。ViewModel使用SavedStateHandle能夠保存資源限制導致重建的數據。
根據傳入的Activity獲取、創建、添加并以鍵值對保存Fragment,從VIewStore的Map中或Factory的create()中獲取ViewMode
1、獲取ViewProvider:
2、獲取ViewModelStore:由前面的源碼可以知道創建ViewProvider時傳入兩個參數:ViewModelStore 和 Factory;顯然從名字就可以看出他們的作用,Factory負責創建,ViewModelStore負責存儲
ViewModelStore內部維護者一個Map集合保存者ViewModel對象的鍵值對
ViewModel的生命周期要比Activity長一點。因為在ComponentActivity 實現了的getViewModelStore ,ViewModelStore在Activity重建前后能保持同一個對象就是通過NonConfigurationInstances實現的。
ActivityThread 里面performLaunchActivity方法里面,啟動Activity 調用了Activity的attach方法,在這個方法,將已有的NonConfigurationInstances賦值給了新的Activity對象。所以Activity 獲取到的ViewMode是同一個,
這樣NonConfigurationInstances能保證ViewModelStore在Activity重建前后是同一個對象,同時也知道為啥ViewModel的生命周期比Activity的生命周期要長一點
LiveData 原理,如何做到生命周期感知:
涉及到LifecycleOwner屬于另一個架構組件 lifecycle,lifecycle原理上面已經講述
偽代碼
//LiveData數據可以再通過observe方法進行數據回調的返回,如上代碼中的onChanged回調。
// 從Livedata添加觀察者的方法 observe 開始:
viewMode.getUsers().observe(this, new Observer<String>() {
@Override
public void onChanged(String users) {
viewmode_text.setText("viewMode獲取到的數據--" + users);
}
});
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
}
第一個參數為LifecycleOwner用于提供當前的生命周期狀態,DESTROYED的時候不做任何操作。
第二個為觀察者observer,首先把observer包裝成了LifecycleBoundObserver,然后把LifecycleBoundObserver維護到mObservers里
private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers = new SafeIterableMap<>();
mObservers是一個LinkedList結構的容器 通過putIfAbsent方法判斷,容器中此觀察者是不是已經存在,如果存在且LifecycleOwner不同的話則拋異常,LifecycleOwner相同則 return 不重復添加。
LifecycleBoundObserver實現了LifecycleObserver,為lifecycle 的觀察者,通過上文的 observe方法添加到了lifecycle觀察中,
接下來主要看LifecycleBoundObserver
通過此類持有 Livedata 的觀察者observer,當 生命周期發生變化時 會回調onStateChanged方法,然后 Livedata 的觀察者在onStateChanged中執行相應的邏輯。
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
//接著執行activeStateChanged
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
if (mActive) {
dispatchingValue(this);
}
}
通過巧妙的設計實現了:
1、狀態沒有變化,什么也不做。
2、變為活(active)就是調用onActive(),非活(inactive)就調用onInactive().
3、另外,變為活的話就調用dispatchingValue方法,此方法為回調觀察者的方法
事件的通知
LiveData通過 setValue 或 postValue 方法去改變持有的數據,并通知觀察者,最終都是調用dispatchingValue()方法:
void dispatchingValue(@Nullable ObserverWrapper initiator) {
........................................
//遍歷之前注冊的觀察者
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
private void considerNotify(ObserverWrapper observer) {
................................
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//開始通知了
observer.mObserver.onChanged((T) mData);
}