Jetpack之ViewModel

2024-10-21  本文已影响0人  Owen270

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() 会被调用?
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 对象呀!

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;
    }

   

}
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();
    }
}
上一篇 下一篇

猜你喜欢

热点阅读