Jetpack 面试: ViewModel 必知的几个问题 (qq.com)
1.ViewModel使用方式
class MainActivity : AppCompatActivity() {
// 创建 ViewModel 方式 1
// 通过 kotlin 委托特性创建 ViewModel
// 需添加依赖 implementation 'androidx.activity:activity-ktx:1.2.3'
// viewModels() 内部也是通过 创建 ViewModel 方式 2 来创建的 ViewModel
private val mainViewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate (savedInstanceState)
setContentView(R.layout.activity_main)
// 创建 ViewModel 方式 2
val mainViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
mainViewModel.systemLiveData.observe(this, Observer<ListDataUiState<SystemResponse>>{
override fun onChanged(t: ListDataUiState<SystemResponse>?) {
}
})
mViewModel.getSystemData(true);
}
}
2.为什么Activity旋转屏幕后ViewModel可以恢复数据?ViewModel 的实例缓存到哪儿了?什么时候 ViewModel#onCleared() 会被调用?
- ViewModelProvider ,ViewModelStoreOwner
public interface ViewModelStoreOwner {
ViewModelStore getViewModelStore();
}
public class ViewModelProvider {
// 获取 owner 对象的 ViewModelStore 对象
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
String canonicalName = modelClass.getCanonicalName();
if (canonicalName == null) {
throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
}
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
// 从 mViewModelStore 缓存中尝试获取
ViewModel viewModel = mViewModelStore.get(key);
// 命中缓存
if (modelClass.isInstance(viewModel)) {
if (mFactory instanceof OnRequeryFactory) {
((OnRequeryFactory) mFactory).onRequery(viewModel);
}
// 返回缓存的 ViewModel 对象
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
// 使用工厂模式创建 ViewModel 实例
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
} else {
viewModel = mFactory.create(modelClass);
}
// 将创建的 ViewModel 实例放进 mViewModelStore 缓存中
mViewModelStore.put(key, viewModel);
// 返回新创建的 ViewModel 实例
return (T) viewModel;
}
}
ViewModelProvider 构造方法的参数类型是 ViewModelStoreOwner ?ViewModelStoreOwner 是什么?我们明明传入的 MainActivity 对象呀!
- MainAcitivty的父类 ComponentActivity
public class ComponentActivity implements ViewModelStoreOwner,LifecycleOwner{
//构造方法中,注入了一个ReportFragment作为被观察者,通过其生命周期通知调用
// ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event)通知观察者
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSavedStateRegistryController.performRestore(savedInstanceState);
ReportFragment.injectIfNeededIn(this);
if (mContentLayoutId != 0) {
setContentView(mContentLayoutId);
}
}
public ComponentActivity() {
//添加观察者
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();
}
}
}
});
}
// 它是 ComponentActivity 的静态内部类
static final class NonConfigurationInstances {
Object custom;
// 果然在这儿
ViewModelStore viewModelStore;
}
public ViewModelStore getViewModelStore() {
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance().
if (nc != null) {
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
//在屏幕旋转的时候,把ViewModelStore实例保存到静态内部类NonConfigurationInstances中
public final Object onRetainNonConfigurationInstance() {
Object custom = onRetainCustomNonConfigurationInstance();
ViewModelStore viewModelStore = mViewModelStore;
if (viewModelStore == null) {
// No one called getViewModelStore(), so see if there was an existing
// ViewModelStore from our last NonConfigurationInstance
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
viewModelStore = nc.viewModelStore;
}
}
if (viewModelStore == null && custom == null) {
return null;
}
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = viewModelStore;
return nci;
}
//通过
public Object getLastNonConfigurationInstance() {
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
}
- ViewModelStore 通过HashMap来存储ViewModel,key为viewModel类的完整包路径和类名,value为viewModel.class
public class ViewModelStore {
// 果不其然,内部有一个 HashMap
private final HashMap<String, ViewModel> mMap = new HashMap<>();
final void put(String key, ViewModel viewModel) {
//如果HashMap插入的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());
}
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
网友评论