微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

深入了解架构组件之ViewModel,android高级面试题汇总

public class DetailFragment extends Fragment {

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

Sharedviewmodel model = viewmodelProviders.of(getActivity()).get(Sharedviewmodel.class);

model.getSelected().observe(this, { item ->

// Update the UI.

});

}

}

仔细体会下这样的好处会发现:

1、Activity 不需要做任何事,甚至不知道这次交互,完美解耦。

2、Fragment 只需要 与viewmodel交互,不需要知道对方 Fragment 的状态甚至是否存在,更不需要持有其引用。所有当对方 Fragment 销毁时,不影响本身任何工作。

3、Fragment 生命周期互不影响,甚至 fragment 替换成其他的 也不影响这个系统的运作。

二、用法简介

======

viewmodel一般配合 LiveData 使用,LiveData可以参考我另一篇文章

首先,获取 viewmodel 实例,通过提供的类viewmodelProviders:

Myviewmodel model = viewmodelProviders.of(activity).get(Myviewmodel.class);

Myviewmodel model = viewmodelProviders.of(fragment).get(Myviewmodel.class);

或带有 Factory 的

Myviewmodel model = viewmodelProviders.of(activity,factory).get(Myviewmodel.class);

VM 内部操作:

public class Myviewmodel extends viewmodel {

private mutablelivedata<List> users;

public LiveData<List> getUsers() {

if (users == null) {

users = new mutablelivedata<List>();

loadUsers();

}

return users;

}

private void loadUsers() {

// Do an asynchronous operation to fetch users.

}

}

然后,可在 activity 观察数据变化:

public class MyActivity extends AppCompatActivity {

public void onCreate(Bundle savedInstanceState) {

// Create a viewmodel the first time the system calls an activity’s onCreate() method.

// Re-created activities receive the same Myviewmodel instance created by the first activity.

Myviewmodel model = viewmodelProviders.of(this).get(Myviewmodel.class);

model.getUsers().observe(this, users -> {

// update UI

});

}

}

三、源码分析原理

========

先从 viewmodel 生命周期开始的时刻着手分析,那么什么时候开始的呢?废话,当然是从我们实例化它开始,那么我们什么时候实例化呢,官网的原话是:

You usually request a ViewModel the first time the system calls an activity object’s onCreate() method.

没错,我们一般在 onCreate 里初始化。

viewmodel 的出生:

实例化的代码很简单,我们慢慢剖析,做了哪些事情

viewmodelProviders.of(activity,factory).get(Myviewmodel.class)

1、 首先是viewmodelProviders 的 of 方法

@MainThread

public static viewmodelProvider of(@NonNull FragmentActivity activity) {

initializefactoryIfNeeded(checkApplication(activity));

return new viewmodelProvider(viewmodelStores.of(activity), sDefaultFactory);

}

@MainThread

public static viewmodelProvider of(@NonNull FragmentActivity activity,

@NonNull Factory factory) {

checkApplication(activity);

return new viewmodelProvider(viewmodelStores.of(activity), factory);

}

参数有 activity 与 fragment 的我就只贴 activity 的了 ,重点看这里引出了一个 Factory,不带Factory的方法只是通过initializefactoryIfNeeded初始化了一个sDefaultFactory(Factory的实现类):

/**

  • Implementations of {@code Factory} interface are responsible to instantiate viewmodels.

*/

public interface Factory {

/**

  • Creates a new instance of the given {@code Class}.

  • @param modelClass a {@code Class} whose instance is requested

  • @param The type parameter for the viewmodel.

  • @return a newly created viewmodel

*/

@NonNull

T create(@NonNull Class modelClass);

}

只有一个 create 方法,用脚指头想想也知道肯定是用来初始化viewmodel的。先放着里等会用到再说。继续看 of 方法

return new viewmodelProvider(viewmodelStores.of(activity), sDefaultFactory)

出现了两个新的类viewmodelProvider与viewmodelStores,先看viewmodelProvider:

public class viewmodelProvider {

private static final String DEFAULT_KEY =

“android.arch.lifecycle.viewmodelProvider.DefaultKey”;

private final Factory mFactory;

private final viewmodelStore mviewmodelStore;

……

@NonNull

@MainThread

public T get(@NonNull String key, @NonNull Class modelClass) {

viewmodel viewmodel = mviewmodelStore.get(key);

if (modelClass.isinstance(viewmodel)) {

//noinspection unchecked

return (T) viewmodel;

} else {

//noinspection StatementWithEmptyBody

if (viewmodel != null) {

// Todo: log a warning.

}

}

viewmodel = mFactory.create(modelClass);

mviewmodelStore.put(key, viewmodel);

//noinspection unchecked

return (T) viewmodel;

}

}

多余的都省略了,此类很简单 就是维护了 一个mFactory,一个新出现的类viewmodelStore(待会会讲),并提供了用mFactory和viewmodelStore生成 viewmodel 的 get 方法。哇,这里就已经看到 viewmodel 最终实例化的地方了,但是别着急还有好多东西呢。

再来看

viewmodelStores.of(activity)

干了啥。先看viewmodelStores:

/**

  • Factory methods for {@link viewmodelStore} class.

*/

@SuppressWarnings(“WeakerAccess”)

public class viewmodelStores {

private viewmodelStores() {

}

/**

  • Returns the {@link viewmodelStore} of the given activity.

  • @param activity an activity whose {@code viewmodelStore} is requested

  • @return a {@code viewmodelStore}

*/

@MainThread

public static viewmodelStore of(@NonNull FragmentActivity activity) {

return holderFragmentFor(activity).getviewmodelStore();

}

/**

  • Returns the {@link viewmodelStore} of the given fragment.

  • @param fragment a fragment whose {@code viewmodelStore} is requested

  • @return a {@code viewmodelStore}

*/

@MainThread

public static viewmodelStore of(@NonNull Fragment fragment) {

return holderFragmentFor(fragment).getviewmodelStore();

}

}

只有两个 of 方法,holderFragmentFor为 HolderFragment 初始化的静态方法, 剧透一下HolderFragment 发挥了至关重要的作用,这里先不讲其重要作用 只看getviewmodelStore()

public class HolderFragment extends Fragment {

……

private viewmodelStore mviewmodelStore = new viewmodelStore();

public viewmodelStore getviewmodelStore() {

return mviewmodelStore;

}

……

}

没啥说的,看viewmodelStore:

public class viewmodelStore {

private final HashMap<String, viewmodel> mMap = new HashMap<>();

final void put(String key, viewmodel viewmodel) {

viewmodel oldviewmodel = mMap.get(key);

if (oldviewmodel != null) {

oldviewmodel.onCleared();

}

mMap.put(key, viewmodel);

}

final viewmodel get(String key) {

return mMap.get(key);

}

/**

  • Clears internal storage and notifies viewmodels that they are no longer used.

*/

public final void clear() {

for (viewmodel vm : mMap.values()) {

vm.onCleared();

}

mMap.clear();

}

}

很明显是一个用来存放 viewmodel 实例的类,内部维护了一个 HashMap 存放 viewmodel,

并提供了 get,put,clear方法

至此viewmodelProviders of 做了哪些事情呢:

1、初始化了viewmodelProvider内部维护了 用于创建 VM 的 Factory,和用户存放 VM 的viewmodelStore;

2、初始化了 用来生成 viewmodel 的 Factory(认为DefaultFactory);

3、通过viewmodelStores的静态方法实例化了 HolderFragment,并实例化了viewmodelStore

2、然后是viewmodelProvider的 get 方法

上面已经贴过了,再贴一下吧:

viewmodelProviders.of(activity,factory).get(Myviewmodel.class);

@NonNull

@MainThread

public T get(@NonNull String key, @NonNull Class modelClass) {

viewmodel viewmodel = mviewmodelStore.get(key);

if (modelClass.isinstance(viewmodel)) {

//noinspection unchecked

return (T) viewmodel;

} else {

//noinspection StatementWithEmptyBody

if (viewmodel != null) {

// Todo: log a warning.

}

}

viewmodel = mFactory.create(modelClass);

mviewmodelStore.put(key, viewmodel);

//noinspection unchecked

return (T) viewmodel;

}

逻辑不复杂,先看viewmodelStore是不是已经存了,没有的话就通过 factory 实例化, 并存到 viewmodelStore 中。

viewmodel 的死亡:

T get(@NonNull String key, @NonNull Class modelClass) {

viewmodel viewmodel = mviewmodelStore.get(key);

if (modelClass.isinstance(viewmodel)) {

//noinspection unchecked

return (T) viewmodel;

} else {

//noinspection StatementWithEmptyBody

if (viewmodel != null) {

// Todo: log a warning.

}

}

viewmodel = mFactory.create(modelClass);

mviewmodelStore.put(key, viewmodel);

//noinspection unchecked

return (T) viewmodel;

}

逻辑不复杂,先看viewmodelStore是不是已经存了,没有的话就通过 factory 实例化, 并存到 viewmodelStore 中。

viewmodel 的死亡:

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐