viewModelScope是如何做到自动解绑网络请求的

本文详细分析了Kotlin协程在Android中如何通过viewModelScope在页面关闭时自动取消网络请求。从初始化ViewModel,到开启协程执行网络请求,再到页面销毁时自动解绑并关闭协程的过程,揭示了viewModelScope自动解绑的原理。
摘要由CSDN通过智能技术生成
建议大家可以对着文章末尾的时序图(画的不咋的)一起看会比较好理解,下面开始吧

最近Kotlin的使用越来越普及,尤其是kotlin协程的使用,更是极大地简化了异步操作,尤其是网络请求,再也不怕线程切换了,从此告别接口回调,和RxJava,对是的,你没听错,暂时告别RxJava,只能说RxJava这把杀牛刀,被我们拿来杀鸡,确实有点大材小用。扯远了,下面开始进入正题,来看看Android的ViewModel的扩展变量,ViewModel.viewModelScope到底是如何在页面关闭的时候,自动关闭协程的(也就是我们的网络请求)。

一、初始化

我们在执行网络请求之前,一般都要先初始化ViewModel,代码如下

mViewModel = ViewModelProvider(this,ViewModelProvider.AndroidViewModelFactory.getInstance(application)).get(tClass) as VM

注意了,看似不起眼的1行代码,可是后面完成自动取消的关键,我们慢慢来分析

这里调用了ViewModelProvider的构造函数,我们点进去看看,这里也很重要

public ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull Factory factory) {
   
        this(owner.getViewModelStore(), factory);
    }

注意一点,此处调用了下面这行代码

owner.getViewModelStore()

owner即当前的Activity,的getViewModelStore方法,此处也很关键,我们点进去看一下,是ViewModelStoreOwner 接口

public interface ViewModelStoreOwner {
   
    /**
     * Returns owned {@link ViewModelStore}
     *
     * @return a {@code ViewModelStore}
     */
    @NonNull
    ViewModelStore getViewModelStore();
}

看一下,我们的BaseActivity的继承关系

BaseActivity  > AppCompatActivity > FragmentActivity  >  ComponentActivity > ViewModelStoreOwner

我们点进去看一下就会发现,最终实现 getViewModelStore() 方法的是 ComponentActivity,如下

  @NonNull
    @Override
    public ViewModelStore getViewModelStore() {
   
        if (getApplication() == null) {
   
            throw new IllegalStateException("Your activity is not yet attached to the "
                    + "Application instance. You can't request ViewModel before onCreate call.");
        }
        if (mViewModelStore == null) {
   
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
   
                // Restore the ViewModelStore from NonConfigurationInstances
                mViewModelStore = nc.viewModelStore;
            }
            if (mViewModelStore == null) {
   
                mViewModelStore = new ViewModelStore();
            }
        }
        return mViewModelStore;
    }

这里主要的作用是初始化了 ViewModelStore ,传递给ViewModelProvider ,这个也很重要,后面会用到。好的,现在我们回到刚才的 mViewModel初始化的地方,就是刚才的第一句代码,还没说完,我们接着看。

mViewModel = ViewModelProvider(this,ViewModelProvider.AndroidViewModelFactory.getInstance(application)).get(tClass) as VM

现在我们来看看,这个get方法

ViewModelProvider(x,x).get(tClass)

点进去以后

@NonNull
    @MainThread
    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 {
   
        //因为我们使用的是默认的Factory,所以这里就不看了,以后如果需要自定义Factory的时候,这里就是我们自定义的Factory的方法
            viewMode
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值