ViewModel的共享(下)

多个 fragment 如何共享一个 ViewModel

首先如果我们想要多个不同的 fragment 中拿到同一份的 ViewModel 我们比较常规的用法如下:
ViewModelProviders.of(this@activity).get(TempViewModel::class.java)
如上代码所示,在 fragment 中获取ViewModel传入同一个 Activity,就能拿到同一个对应类型的 ViewModel对象。

怎么拿 ViewModel?

@NonNull
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity,
        @Nullable Factory factory) {
    Application application = checkApplication(activity);
    if (factory == null) {
        factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
    }
    return new ViewModelProvider(activity.getViewModelStore(), factory);
}

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

@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
    ViewModel viewModel = mViewModelStore.get(key);

    if (modelClass.isInstance(viewModel)) {
        if (mFactory instanceof OnRequeryFactory) {
            ((OnRequeryFactory) mFactory).onRequery(viewModel);
        }
        return (T) viewModel;
    } else {
        //noinspection StatementWithEmptyBody
        if (viewModel != null) {
            // TODO: log a warning.
        }
    }
    if (mFactory instanceof KeyedFactory) {
        viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
    } else {
        viewModel = mFactory.create(modelClass);
    }
    mViewModelStore.put(key, viewModel);
    return (T) viewModel;
}

首先通过静态的 of() 方法我们可以看到,实际上创建的时候传入的一个 ViewModelStore、 factory 创建出 ViewModelProvider。 然后调用 get()方法来获取对应类型的 ViewModel。
在 get()方法中,会根据传入的 key(可以自定义)去判断 ViewModelStore 中是否有已经创建的 ViewModel,有的话直接返回,没有的话,会根据前面传入的(默认创建的或是传进来) factory 去创建指定ViewModel,然后存到这个 ViewModelStore中,并且返回 ViewModel。

  1. ViewModelStore是啥?
  2. factory 做了什么工作?
  3. 为什么能拿到同一个 ViewModel?

ViewModelStore是啥?

ViewModelStore 是什么?简单的理解,那就是用于存储 ViewModel,原理也很简单,内部维护一个 HashMap<String, ViewModel>,我们每次通过 get()方法来获取ViewModel 时,都会到这个 hashmap 中去寻找,是否有对应的实例。

public class ViewModelStore {

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

    final void put(String key, ViewModel viewModel) {
        ViewModel oldViewModel = mMap.put(key, viewModel);
        if (oldViewModel != null) {
            oldViewModel.onCleared();
        }
    }

    final ViewModel get(String key) {
        return mMap.get(key);
    }

    Set<String> keys() {
        return new HashSet<>(mMap.keySet());
    }

    /**
     *  Clears internal storage and notifies ViewModels that they are no longer used.
     */
    public final void clear() {
        for (ViewModel vm : mMap.values()) {
            vm.clear();
        }
        mMap.clear();
    }
}

为什么能拿到同一个ViewModel?

通过上面代码我们就可以看到,只要传入的 ViewModelStore 相同,对应的 key 相同,我们就可以拿到同一个。

如何跨 Activity共享ViewModel

所以通过上面的知识,我们可以知道,只要多个 activity 在获取 ViewModel 时传入同一个 ViewModelStore、同一个 ViewModel Class就可以从对应的 ViewModelStore 中获取到同一份ViewModel了。这样一来就可以实现在跨不同生命周期对象来共享同一份ViewModel。但是需要注意的是,需要考虑传入的 ViewModelStore 的生命周期。

除此之外,我们还可以通过传入不同的Key,来获取不同实例的同类型ViewModel,具体可阅读ViewModel源码,已经有现成的API提供给我们使用。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值