#頭條創作挑戰賽#
本文通過在網易面試遇到的問題總結而出,如有不對的地方,請及時批評指正。篇幅較長,請耐心閱讀。如果您想了解其他架構源碼,歡迎評論區留言!
簡介
ViewModel作為谷歌Jetpack重要元件之一,它可以目前頁面緩存狀态并可在配置更改後持久保留相應狀态。
使用步驟
ViewModel
1.定義MainViewModel類繼承ViewModel()
class MainViewModel:ViewModel() {
val mainLiveData = MutableLiveData<String>()
}
2.在activity中通過ViewModelProvider擷取MainViewModel執行個體對象。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val viewModel = ViewModelProvider(this, ViewModelProvider.NewInstanceFactory()).
get(MainViewModel::class.java)
viewModel.mainLiveData.observe(this){
}
}
通過定義一個MainViewModel類繼承自ViewModel抽象類,然後再Activity中初始化MainViewModel。
AndroidViewModel
- 如果需要在ManViewModel中使用context,MainViewModel需要繼承AndroidViewModel。
class MainViewModel(application: Application):AndroidViewModel(application) {
val mainLiveData = MutableLiveData<String>()
}
2 .使用ViewModelProvider擷取MainViewModel執行個體對象
val viewModel = ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory(application)).get(MainViewModel::class.java)
viewModel.mainLiveData.observe(this){
}
源碼分析
Activity綁定
1 .Activity的父類ComponentActivity實作了ViewModelStoreOwner接口,
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
ContextAware,
LifecycleOwner,
ViewModelStoreOwner,
}
2 .ViewModelStoreOwner中定義了getViewModelStore方法用來提供ViewModelStore。
public interface ViewModelStoreOwner {
//傳回一個ViewModelStore
@NonNull
ViewModelStore getViewModelStore();
}
3 .ViewModelStore中定義HashMap用來儲存ViewModel執行個體。
public class ViewModelStore {
//定義HashMap集合存儲ViewModel
private final HashMap<String, ViewModel> mMap = new HashMap<>();
//存儲ViewModel
final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
//根據key值擷取對應的ViewModel
final ViewModel get(String key) {
return mMap.get(key);
}
Set<String> keys() {
return new HashSet<>(mMap.keySet());
}
/**
* 回收所有ViewModel并清空HashMap.
*/
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
4 .由于ComponentActivity實作了ViewModelStoreOwner接口,在ComponentActivity中調用getViewModelStore可以擷取ViewModel的存儲類ViewModelStore,ViewModelStore中使用HashMap存儲ViewModel,如果存儲的ViewModel的key值相同,則删除oldViewModel舊的ViewModel,替換成最新的ViewModel。
5 . ComponentActivity中使用Lifecycle對目前activity生命周期進行監聽,并在on Destroy生命周期中對儲存在ViewModelStore中的ViewModel進行清空釋放。
public ComponentActivity() {
Lifecycle lifecycle = getLifecycle();
......................
.........................
//使用lifecycle對activity生命周期進行監聽
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
//如果生命周期為onDestory
if (event == Lifecycle.Event.ON_DESTROY) {
// 清除context
mContextAwareHelper.clearAvailableContext();
//如果應用配置沒有發生改變
if (!isChangingConfigurations()) {
//清除ViewModelStore中HashMap存儲的ViewModel
getViewModelStore().clear();
}
}
}
});
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
//初始化ViewModelStore
ensureViewModelStore();
getLifecycle().removeObserver(this);
}
});
當ComponentActivity退出銷毀時,會調用getViewModelStore().clear(),清除ViewModelStore中HashMap存儲的ViewModel,釋放資源。
6 .調用ensureViewModelStore進行ViewModelStore進行初始化。
void ensureViewModelStore() {
//如果存儲類為null
if (mViewModelStore == null) {
//擷取上一個儲存的NonConfigurationInstances執行個體對象
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// 從 NonConfigurationInstances 恢複 ViewModelStore
mViewModelStore = nc.viewModelStore;
}
//否則建立新的ViewModelStore
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
}
static final class NonConfigurationInstances {
Object custom;
//成員變量用來儲存ViewModelStore
ViewModelStore viewModelStore;
}
NonConfigurationInstances是一個靜态類,它有兩個成員變量Object 和ViewModelStore ;如果ViewModelstore如果不存在,則将NonConfigurationInstances的成員變量儲存的ViewModelstore指派給ViewModelStore 。
//擷取上一次儲存的資料
@Nullable
public Object getLastNonConfigurationInstance() {
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
mLastNonConfigurationInstances 是上一次儲存的資料執行個體,當Activity被建立的時候,調用attach方法,mLastNonConfigurationInstances = lastNonConfigurationInstances;當應用配置發生改變時,如螢幕旋轉,會導緻Activity重建,這個時候會擷取上一次儲存的mLastNonConfigurationInstances ,并取出其中存儲的viewModeStore,最後得到ViewModel,直接從ViewModel中得到資料恢複界面清單。
ViewModel儲存
1 .使用ViewModelProvider建立ViewModel。
public static ViewModelProvider of(@NonNull FragmentActivity activity) {
//建立ViewModelProvider對象
return new ViewModelProvider(activity);
}
2 .由于目前activity實作ViewModelStoreOwner接口,是以可以通過getViewModelStore方法擷取ViewModelStore對象。
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
//由于目前activity實作ViewModelStoreOwner接口,
//是以可以通過getViewModelStore方法擷取ViewModelStore對象。
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
mViewModelStore = store;
}
3 . 使用工廠模式建立ViewModel同時儲存到ViewModelStore中。
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
//擷取activity中的ViewModel
ViewModel viewModel = mViewModelStore.get(key);
..........
//使用工廠模式建立viewModel執行個體
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
} else {
viewModel = (mFactory).create(modelClass);
}
//将viewModel存入ViewModelStore中
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
ViewModel銷毀
當activity退出銷毀時,通過lifecycle對activity的生命周期監聽,如果配置沒有發生改變,正常退出,則直接情況ViewModelStore。
//使用lifecycle對activity生命周期進行監聽
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
//如果生命周期為onDestory
if (event == Lifecycle.Event.ON_DESTROY) {
// 清除context
mContextAwareHelper.clearAvailableContext();
//如果應用配置沒有發生改變
if (!isChangingConfigurations()) {
//清除ViewModelStore中HashMap存儲的ViewModel
getViewModelStore().clear();
}
}
}
});
總結如下:
Activity通過實作ViewModelStoreOwner接口,得到ViewModelStore,将ViewModel儲存到ViewModelStore中的HashMap中。同時使用LifeCycle監聽Activity生命周期,在onDestroy中進行ViewModel的主動釋放。
以上就是網易面試後總結的幾個要點,還不會的同學趕緊學起來吧,感謝您的閱讀,創造不易,如果您覺得本篇文章對您有幫助,請點選關注小編,您的支援就是小編創作的最大動力!