viewModel源码

基本使用:

class ChooseAreaViewModel :ViewModel(){
	var provinceLiveData = MutableLiveData<MutableList<Province>>()

    fun getProvinceList(){
        viewModelScope.launch {
            provinceLiveData.value = PlaceRepository.getProvinceList()
        }
    }
}
class MVVMActivity:AppCompatActivity() {
	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_mvvm)
        viewModel = ViewModelProviders.of(this).get(ChooseAreaViewModel::class.java)
        viewModel.provinceLiveData.observe(this, Observer {result->
            Log.e("TAG",result[0].provinceName)
            Log.e("TAG",Thread.currentThread().name)
            text.text = result[0].provinceName+result[0].code+result[0].provinceCode
        })
    }
}

源码解析
首先构建ViewModelProvider

    public static ViewModelProvider of(@NonNull FragmentActivity activity,
            @Nullable Factory factory) {
        Application application = checkApplication(activity);
        if (factory == null) {
        //单例获取ViewModelFactory,后续会只用该类通过反射传建对应的viewModel
            factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
        }
        return new ViewModelProvider(activity.getViewModelStore(), factory);
    }

调用ViewModelProvider的get方法获取viewModel

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

public static class NewInstanceFactory implements Factory {
        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
            //noinspection TryWithIdenticalCatches
            try {
                //反射创建viewModel实例
                return modelClass.newInstance();
            } catch (InstantiationException e) {
                throw new RuntimeException("Cannot create an instance of " + modelClass, e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Cannot create an instance of " + modelClass, e);
            }
        }
}

从viewModelStore中获取viewModel,如果不存在则创建完成viewModel后添加到ViewModelStore里面的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中,而viewModel生命周期比activity长,在这里插入图片描述
因此我们重点关注viewModelStore生命周期
获取ViewModelStore,首先从ComponentActivity类中调用getViewModelStore

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        LifecycleOwner,
        ViewModelStoreOwner,
        SavedStateRegistryOwner,
        OnBackPressedDispatcherOwner {

	@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.");
        }
        //判断该ComponentActivity中的mViewModelStore是否为空,activity初次创		       
        次创建后为空,当屏幕旋转后不为空使用第一次创建的ViewModelStore
        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包装在NonConfigurationInstances类中
    @Override
    @Nullable
    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;
    }
}

由上面可知viewModelStore在activity初次创建时为空,当屏幕反转时使用第一次的viewModelStore,当屏幕反转时viewModelStore是如何保存的

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback,
        AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {  
        
      NonConfigurationInstances retainNonConfigurationInstances() {
        Object activity = onRetainNonConfigurationInstance();
        HashMap<String, Object> children = onRetainNonConfigurationChildInstances();
        FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();

        // We're already stopped but we've been asked to retain.
        // Our fragments are taken care of but we need to mark the loaders for retention.
        // In order to do this correctly we need to restart the loaders first before
        // handing them off to the next activity.
        mFragments.doLoaderStart();
        mFragments.doLoaderStop(true);
        ArrayMap<String, LoaderManager> loaders = mFragments.retainLoaderNonConfig();

        if (activity == null && children == null && fragments == null && loaders == null
                && mVoiceInteractor == null) {
            return null;
        }

        NonConfigurationInstances nci = new NonConfigurationInstances();
        nci.activity = activity;
        nci.children = children;
        nci.fragments = fragments;
        nci.loaders = loaders;
        if (mVoiceInteractor != null) {
            mVoiceInteractor.retainInstance();
            nci.voiceInteractor = mVoiceInteractor;
        }
        return nci;
    }  
}

首先在activity类中调用retainNonConfigurationInstances()方法,在该方法中再次调用ComponentActivity的onRetainNonConfigurationInstance方法对viewModel进行包装,然后再retainNonConfigurationInstances方法中再次进行包装,接下来看activity类中etainNonConfigurationInstances()方法如何调用的

在ActivityThread类中当屏幕进行旋转会发送RELAUNCH_ACTIVITY信号,然后调用handleRelaunchActivityLocally方法,最终调用handleRelaunchActivity方法,具体可参考android activity详细启动调用

接下来看ActivityThread类中的handleRelaunchActivity方法

public void handleRelaunchActivity(ActivityClientRecord tmp,
            PendingTransactionActions pendingActions) {
	......
	handleRelaunchActivityInner(r, configChanges, tmp.pendingResults, tmp.pendingIntents,
                pendingActions, tmp.startsNotResumed, tmp.overrideConfig, "handleRelaunchActivity");
    .......
}

private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges,
            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingIntents,
            PendingTransactionActions pendingActions, boolean startsNotResumed,
            Configuration overrideConfig, String reason) {
    ........
    handleDestroyActivity(r.token, false, configChanges, true, reason);
    ........
}

public void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
            boolean getNonConfigInstance, String reason) {
    ActivityClientRecord r = performDestroyActivity(token, finishing,
                configChanges, getNonConfigInstance, reason);
    ........
    handleLaunchActivity(r, pendingActions, customIntent);
}

/** Core implementation of activity destroy call. */
ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
            int configChanges, boolean getNonConfigInstance, String reason) {
    ActivityClientRecord r = mActivities.get(token);
	........
	r.lastNonConfigurationInstances
                            = r.activity.retainNonConfigurationInstances();
	........
    try {
         r.activity.mCalled = false;
         mInstrumentation.callActivityOnDestroy(r.activity);
         if (!r.activity.mCalled) {
             throw new SuperNotCalledException(
                        "Activity " + safeToComponentShortString(r.intent) +
                        " did not call through to super.onDestroy()");
        }
        if (r.window != null) {
             r.window.closeAllPanels();
        }
        } catch (SuperNotCalledException e) {
             throw e;
        } catch (Exception e) {
             if (!mInstrumentation.onException(r.activity, e)) {
                  throw new RuntimeException(
                            "Unable to destroy activity " + safeToComponentShortString(r.intent)
                            + ": " + e.toString(), e);
                }
            }
        r.setState(ON_DESTROY);
      ......      
}

可以看到通过一系列调用最终调用performDestroyActivity,该方法调用activity.retainNonConfigurationInstances后,把activity.retainNonConfigurationInstances中包装的viewModel保存在ActivityClientRecord的lastNonConfigurationInstances属性中,再调用mInstrumentation.callActivityOnDestroy(r.activity)方法通知activity调用onDestory方法

保存在ActivityClientRecord的lastNonConfigurationInstances属性,如何获取的呢,可以看到在handleDestroyActivity方法中调用performDestroyActivity方法后,最终会调用handleLaunchActivity方法

public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
    .......
    final Activity a = performLaunchActivity(r, customIntent);
    .......        
}

/**  Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
	.......
	activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback,
                        r.assistToken);
	.......
}

可以看到在performLaunchActivity中会调用activity.attach方法,该方法中包含参数r.lastNonConfigurationInstances

总结:当activity首次创建时首先会new一个viewModelStore,然后经过一些列包装会把该viewModelStore保存在activity类中的NonConfigurationInstances的静态内部类中,然后再ActivityThread类中当收到屏幕反转的信号,最终调用performDestroyActivity方法,在该方法中把activity类中的NonConfigurationInstances保存在ActivityClientRecord的lastNonConfigurationInstances属性中,然后才会通知activity调用onDestory。
当上述保存操作执行后,会调用performLaunchActivity方法,该方法会调用activity.attach方法,传入上述保存的ActivityClientRecord的lastNonConfigurationInstances属性

当调用finish方法结束当前activity时由于不会触发activity.retainNonConfigurationInstances()方法,因此不会进行保存ViewModelStore,故需要清空ViewModelStore中保存的viewModel

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

可以看到这里使用lifecycle进行监听,当页面onDestory时,如果不是有屏幕反转之类的导致的,那么将清空ViewModelStore中存储的viewModel

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值