Android开发 ViewModel_2_了解多种自定义实例方式 (Factory 与 key)
<h1><span style="color: rgba(0, 128, 128, 1)">前言</span></h1><p> ViewModel的虽然可以以很简单方便的<span style="color: rgba(0, 0, 0, 1)"> ViewModelProviders.of(getActivity()).get(ViewModel.class); 但是这只是google提供的简单构建,你需要引入下面的库才能使用:</span></p>
<div class="cnblogs_code">
<pre>implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"</pre>
</div>
<p><span style="color: rgba(0, 0, 0, 1)">但是!<span style="color: rgba(0, 0, 0, 1)">远远不止这样。l还可以使用ViewModelProvider.Factory自定义实例ViewModel(其实继承工厂类实例ViewModel才是google推荐的,这点在Android studio的模板代码里可以看到)</span></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"> 转载请注明来源:https://www.cnblogs.com/guanxinjing/p/12198971.html</span></span></p>
<h1><span style="color: rgba(0, 128, 128, 1); background-color: rgba(255, 255, 255, 1)">为什么要学习ViewModel自定义实例?</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"> 那么你可能会疑问了,使用 <span style="color: rgba(0, 0, 0, 1)">ViewModelProviders.of(getActivity()).get(ViewModel.class); </span>创建ViewModel这么简单轻松,为什么还要自己构建Factory呢。原因有以下几点:</span></span></span></span></p>
<ol>
<li><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">如果你继承的ViewModel类是有参构造,那么上面这个方式是不支持在实例ViewModel的传参的,所以需要自己构建<span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">Factory</span></span>类</span></span></span></span></li>
<li><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">一个Activity可能根据业务会有多个不同的ViewModel,那么根据不同的业务下配置不同的ViewModel,<span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">需要自己构建<span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">Factory类</span></span></span></span></span></span>,来根据类别返回不同的ViewModel给外部(这也是工厂模式的核心,解决接口选择的问题)</span></span></span></span></li>
</ol>
<h1><span style="color: rgba(0, 128, 128, 1)"><span style="color: rgba(0, 128, 128, 1)">了解</span>ViewModel的构建原理</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)"> 因为后续的使用ViewModelProvider.Factory创建ViewModel,所以我们必需了解一些些ViewModel构建、保存、移除原理。好在有一个参照物可以阅读理解,那就是上面提到以<span style="color: rgba(0, 0, 0, 1)"> ViewModelProviders </span>形式的构建<span style="color: rgba(0, 0, 0, 1)">ViewModel</span>。对照着它看基本上就能明白一些东西了。</span></p>
<h2><span style="color: rgba(0, 0, 0, 1)">看看 <span style="color: rgba(0, 0, 0, 1)">ViewModelProviders.of() 干了啥事情</span></span></h2>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">我们点击进入源码后可以看到如下代码</span></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)"> @NonNull
@MainThread
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> ViewModelProvider of(@NonNull FragmentActivity activity) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> of(activity, <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">);
}</span></pre>
</div>
<p>恩,of又去调用了一个重载的of,但是传入了一个activity或者Fragment 和 一个null ,我们看看这个2个参数的of干了什么</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)"> @NonNull
@MainThread
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> ViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
Application application </span>= checkApplication(activity); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">源码在这里检查了一下activity的application</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (factory == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">它拿application去创建了一个Factory类
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这个factory其实就是构建ViewModel的工厂类</span>
factory =<span style="color: rgba(0, 0, 0, 1)"> ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">实例化了一个ViewModelProvider,
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">在activity里取得ViewModelStore(这个东西是用于保存ViewModel使用的),也传入了
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">并且也把Factory类一起传入
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">其实ViewModelStore和factory传入后就直接成为成员变量缓存了,等待你调用get方法来创建ViewModel</span>
<span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ViewModelProvider(activity.getViewModelStore(), factory);
}</span></pre>
</div>
<p>我们可以看看<span style="color: rgba(0, 0, 0, 1)">ViewModelProvider.AndroidViewModelFactory.getInstance(application)</span> 这行代码</p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> AndroidViewModelFactory sInstance;
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* Retrieve a singleton instance of AndroidViewModelFactory.
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> application an application to pass in {</span><span style="color: rgba(128, 128, 128, 1)">@link</span><span style="color: rgba(0, 128, 0, 1)"> AndroidViewModel}
* </span><span style="color: rgba(128, 128, 128, 1)">@return</span><span style="color: rgba(0, 128, 0, 1)"> A valid {</span><span style="color: rgba(128, 128, 128, 1)">@link</span><span style="color: rgba(0, 128, 0, 1)"> AndroidViewModelFactory}
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
@NonNull
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> AndroidViewModelFactory getInstance(@NonNull Application application) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (sInstance == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
sInstance </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> AndroidViewModelFactory(application);
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> sInstance;
}</span></pre>
</div>
<p>可以看到,直接给你了一个有Application的全局单例的<span style="color: rgba(0, 0, 0, 1)">Factory类。</span></p>
<h2><span style="color: rgba(0, 0, 0, 1)">接下来看看<span style="color: rgba(0, 0, 0, 1)">ViewModelProviders.of().get(<span style="color: rgba(0, 0, 128, 1); font-weight: bold">)</span></span> get方法干了啥事 </span></h2>
<p> get()方法其实就是实现了<span style="color: rgba(0, 0, 0, 1)"> factory 创建 与 ViewModelStore保存 ViewModel,并且返回<span style="color: rgba(0, 0, 0, 1)">ViewModel</span>。 我们可以看看下面这些代码</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)"> @NonNull
@MainThread
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <T <span style="color: rgba(0, 0, 255, 1)">extends</span> ViewModel> T get(@NonNull Class<T><span style="color: rgba(0, 0, 0, 1)"> modelClass) {
String canonicalName </span>= modelClass.getCanonicalName(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取了传入的实现的ViewModel的类名</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (canonicalName == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> IllegalArgumentException("Local and anonymous classes can not be ViewModels"<span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">因为我们没有传入key,所以这里直接用类名取代的成为了key
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">然后就进入下面这个重载的get方法里进行实现了</span>
<span style="color: rgba(0, 0, 255, 1)">return</span> get(DEFAULT_KEY + ":" +<span style="color: rgba(0, 0, 0, 1)"> canonicalName, modelClass);
}
@NonNull
@MainThread
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <T <span style="color: rgba(0, 0, 255, 1)">extends</span> ViewModel> T get(@NonNull String key, @NonNull Class<T><span style="color: rgba(0, 0, 0, 1)"> modelClass) {
ViewModel viewModel </span>= mViewModelStore.get(key);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">去查找这个ViewModelStore 对应key的保存viewModel</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (modelClass.isInstance(viewModel)) { <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">检查一下这个viewModel是不是已经实例化,不是null
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">noinspection unchecked</span>
<span style="color: rgba(0, 0, 255, 1)">return</span> (T) viewModel;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果已经实例化,不等于null就直接返回</span>
} <span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">noinspection StatementWithEmptyBody</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (viewModel != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> TODO: log a warning.</span>
<span style="color: rgba(0, 0, 0, 1)"> }
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">下面就用传入的Factory类来实例化你需要的ViewModel</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (mFactory <span style="color: rgba(0, 0, 255, 1)">instanceof</span> KeyedFactory) { <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这里检查是不是带key</span>
viewModel =<span style="color: rgba(0, 0, 0, 1)"> ((KeyedFactory) (mFactory)).create(key, modelClass);
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
viewModel </span>=<span style="color: rgba(0, 0, 0, 1)"> (mFactory).create(modelClass); <span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)">这里的create使用了反射的形式创建实例</span></span>
}
mViewModelStore.put(key, viewModel); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">然后存一下ViewModel
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">noinspection unchecked</span>
<span style="color: rgba(0, 0, 255, 1)">return</span> (T) viewModel; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">返回viewModel</span>
}</pre>
</div>
<h2>移除缓存的<span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">ViewModel</span></span></h2>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"> 其实蛛丝马迹就在<span style="color: rgba(0, 0, 0, 1)">ViewModelStore</span>里</span></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ViewModelStore {
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">final</span> HashMap<String, ViewModel> mMap = <span style="color: rgba(0, 0, 255, 1)">new</span> HashMap<><span style="color: rgba(0, 0, 0, 1)">();
</span><span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> put(String key, ViewModel viewModel) {
ViewModel oldViewModel </span>=<span style="color: rgba(0, 0, 0, 1)"> mMap.put(key, viewModel);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (oldViewModel != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
oldViewModel.onCleared();
}
}
</span><span style="color: rgba(0, 0, 255, 1)">final</span><span style="color: rgba(0, 0, 0, 1)"> ViewModel get(String key) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> mMap.get(key);
}
Set</span><String><span style="color: rgba(0, 0, 0, 1)"> keys() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> HashSet<><span style="color: rgba(0, 0, 0, 1)">(mMap.keySet());
}
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
*Clears internal storage and notifies ViewModels that they are no longer used.
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">void</span> clear() { <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这里清理了当前Activity或者Fragment的所有ViewModel,这个方法是在Activity或者Fragment在销毁的时候有调用的</span>
<span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}</span></pre>
</div>
<h1> </h1>
<h1><span style="color: rgba(0, 128, 128, 1)">使用ViewModelProvider.Factory实现创建ViewModel</span></h1>
<h2> 使用反射创建无参实例(在上面的源码上可以看到的创建方式,这样一个Factory就可以传入继承ViewModel的泛型,加以实例)</h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> MainViewModelFactory <span style="color: rgba(0, 0, 255, 1)">implements</span><span style="color: rgba(0, 0, 0, 1)"> ViewModelProvider.Factory {
@NonNull
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <T <span style="color: rgba(0, 0, 255, 1)">extends</span> ViewModel> T create(@NonNull Class<T><span style="color: rgba(0, 0, 0, 1)"> modelClass) {
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> modelClass.newInstance(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">使用newInstance反射实例ViewModel,并且传出去</span>
} <span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (IllegalAccessException e) {
e.printStackTrace();
} </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (InstantiationException e) {
e.printStackTrace();
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
}
}</span></pre>
</div>
<p><span style="color: rgba(0, 0, 0, 1)">使用MainViewModelFactory创建ViewModel,<strong><span style="color: rgba(255, 0, 0, 1)">注意!</span>千万别自己就使用Factory直接创建ViewModel</strong>,因为上面的get()源码里说明了,这个ViewModel是还需要保存到ViewModelStore里面的,而ViewModelStore的put方法是私有方法。所以我们还是需要交给ViewModelProviders.of().get();来创建让它帮我们保存到<span style="color: rgba(0, 0, 0, 1)">ViewModelStore</span>里,代码如下:</span></p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> MainViewModel mMainViewModel;
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> initViewModel() {
MainViewModelFactory mainViewModelFactory </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MainViewModelFactory();
mMainViewModel </span>= ViewModelProviders.of(<span style="color: rgba(0, 0, 255, 1)">this</span>, mainViewModelFactory).get(MainViewModel.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
}</span></pre>
</div>
<h2>使用反射创建有参实例</h2>
<p>代码如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> MainViewModelFactory4 <span style="color: rgba(0, 0, 255, 1)">implements</span><span style="color: rgba(0, 0, 0, 1)"> ViewModelProvider.Factory {
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> String mValue;
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> MainViewModelFactory4(String value){
mValue </span>=<span style="color: rgba(0, 0, 0, 1)"> value;
}
@NonNull
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <T <span style="color: rgba(0, 0, 255, 1)">extends</span> ViewModel> T create(@NonNull Class<T><span style="color: rgba(0, 0, 0, 1)"> modelClass) {
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
Class[] parameterTypeArray </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Class[]{String.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">};
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> modelClass.getConstructor(parameterTypeArray).newInstance(mValue);
} </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (IllegalAccessException e) {
e.printStackTrace();
} </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (InstantiationException e) {
e.printStackTrace();
} </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (NoSuchMethodException e) {
e.printStackTrace();
} </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (InvocationTargetException e) {
e.printStackTrace();
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
}
}</span></pre>
</div>
<p>还是跟上面一样使用<span style="color: rgba(0, 0, 0, 1)">ViewModelProviders.of().get();</span>来创建。</p>
<h2>简单暴力直接实例目标ViewModel</h2>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> MainViewModelFactory <span style="color: rgba(0, 0, 255, 1)">implements</span><span style="color: rgba(0, 0, 0, 1)"> ViewModelProvider.Factory {
@NonNull
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <T <span style="color: rgba(0, 0, 255, 1)">extends</span> ViewModel> T create(@NonNull Class<T><span style="color: rgba(0, 0, 0, 1)"> modelClass) {
MainViewModel mainViewModel </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MainViewModel();
mainViewModel.setContent(</span>"设置初始化值"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (T)mainViewModel;
}
}</span></pre>
</div>
<p>还是跟上面一样使用<span style="color: rgba(0, 0, 0, 1)">ViewModelProviders.of().get();来创建。</span></p>
<h1><span style="color: rgba(0, 128, 128, 1)">使用KEY创建ViewModel</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">这没啥好说的,就是根据不同的key创建独立数据与内存地址的ViewModel,他们之间数据不互通。</span></span></p>
<p> </p>
<div class="cnblogs_code">
<pre> mMainViewModel1 = ViewModelProviders.of(<span style="color: rgba(0, 0, 255, 1)">this</span>).get("1", MainViewModel.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
mMainViewModel2 </span>= ViewModelProviders.of(<span style="color: rgba(0, 0, 255, 1)">this</span>).get("2", MainViewModel.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
mMainViewModel3 </span>= ViewModelProviders.of(<span style="color: rgba(0, 0, 255, 1)">this</span>).get("3", MainViewModel.<span style="color: rgba(0, 0, 255, 1)">class</span>);</pre>
</div>
<p> </p>
<h1><span style="color: rgba(0, 128, 128, 1)">关于ViewModelProvider.NewInstanceFactory</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">也是继承Factory,然后帮你实现了newInstance();如果你只是简简单单实例一个ViewModel,可以直接继承这个,我们可以看源码:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* Simple factory, which calls empty constructor on the give class.
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">class</span> NewInstanceFactory <span style="color: rgba(0, 0, 255, 1)">implements</span><span style="color: rgba(0, 0, 0, 1)"> Factory {
@SuppressWarnings(</span>"ClassNewInstance"<span style="color: rgba(0, 0, 0, 1)">)
@NonNull
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <T <span style="color: rgba(0, 0, 255, 1)">extends</span> ViewModel> T create(@NonNull Class<T><span style="color: rgba(0, 0, 0, 1)"> modelClass) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">noinspection TryWithIdenticalCatches</span>
<span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> modelClass.newInstance();
} </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (InstantiationException e) {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> RuntimeException("Cannot create an instance of " +<span style="color: rgba(0, 0, 0, 1)"> modelClass, e);
} </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (IllegalAccessException e) {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> RuntimeException("Cannot create an instance of " +<span style="color: rgba(0, 0, 0, 1)"> modelClass, e);
}
}
}</span></pre>
</div>
<h1><span style="color: rgba(0, 128, 128, 1)">关于ViewModelProvider.AndroidViewModelFactory</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">带application的工厂类,你需要配置一个需要application的ViewModel,可以直接使用这个单例的AndroidViewModelFactory。可以看源码(下面的代码上面已经贴了一部分了,这里贴全),需要一个构造方式是传入<span style="color: rgba(0, 0, 0, 1)">application</span>的ViewModel:</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">class</span> AndroidViewModelFactory <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> ViewModelProvider.NewInstanceFactory {
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> AndroidViewModelFactory sInstance;
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* Retrieve a singleton instance of AndroidViewModelFactory.
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> application an application to pass in {</span><span style="color: rgba(128, 128, 128, 1)">@link</span><span style="color: rgba(0, 128, 0, 1)"> AndroidViewModel}
* </span><span style="color: rgba(128, 128, 128, 1)">@return</span><span style="color: rgba(0, 128, 0, 1)"> A valid {</span><span style="color: rgba(128, 128, 128, 1)">@link</span><span style="color: rgba(0, 128, 0, 1)"> AndroidViewModelFactory}
</span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">
@NonNull
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> AndroidViewModelFactory getInstance(@NonNull Application application) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (sInstance == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">) {
sInstance </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> AndroidViewModelFactory(application);
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> sInstance;
}
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> Application mApplication;
</span><span style="color: rgba(0, 128, 0, 1)">/**</span><span style="color: rgba(0, 128, 0, 1)">
* Creates a {</span><span style="color: rgba(128, 128, 128, 1)">@code</span><span style="color: rgba(0, 128, 0, 1)"> AndroidViewModelFactory}
*
* </span><span style="color: rgba(128, 128, 128, 1)">@param</span><span style="color: rgba(0, 128, 0, 1)"> application an application to pass in {</span><span style="color: rgba(128, 128, 128, 1)">@link</span><span style="color: rgba(0, 128, 0, 1)"> AndroidViewModel}
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> AndroidViewModelFactory(@NonNull Application application) {
mApplication </span>=<span style="color: rgba(0, 0, 0, 1)"> application;
}
@NonNull
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <T <span style="color: rgba(0, 0, 255, 1)">extends</span> ViewModel> T create(@NonNull Class<T><span style="color: rgba(0, 0, 0, 1)"> modelClass) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (AndroidViewModel.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">.isAssignableFrom(modelClass)) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">noinspection TryWithIdenticalCatches</span>
<span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> modelClass.getConstructor(Application.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">).newInstance(mApplication);
} </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (NoSuchMethodException e) {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> RuntimeException("Cannot create an instance of " +<span style="color: rgba(0, 0, 0, 1)"> modelClass, e);
} </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (IllegalAccessException e) {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> RuntimeException("Cannot create an instance of " +<span style="color: rgba(0, 0, 0, 1)"> modelClass, e);
} </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (InstantiationException e) {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> RuntimeException("Cannot create an instance of " +<span style="color: rgba(0, 0, 0, 1)"> modelClass, e);
} </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (InvocationTargetException e) {
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> RuntimeException("Cannot create an instance of " +<span style="color: rgba(0, 0, 0, 1)"> modelClass, e);
}
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.create(modelClass);
}
}</span></pre>
</div>
<p> </p>
<p>End</p>
</div>
<div id="MySignature" role="contentinfo">
<div style="text-align: center">
<p style="color:orange;font-size:16px;" >本文来自博客园,作者:观心静 ,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/12198971.html </p>
<div style="color:orange;font-size:16px;">本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。 </div>
</div><br><br>
来源:https://www.cnblogs.com/guanxinjing/p/12198971.html
頁:
[1]