JetPack框架组件3——ViewModel的使用和源码分析

JetPack框架组件3——ViewModel的使用和源码分析

一.ViewModel的使用和概述

1.使用场景

ViewModel是什么,ViewModel就是Activity/Fragment中的一个实体,是为了帮助Activity/fragmet承担业务逻辑,负责activity和model的沟通,承担资源的获取和释放工作,让activity和只承担ui变化的逻辑。

2.ViewModel生命周期

下图是ViewModel的生命周期
在这里插入图片描述
ViewModel的存在时间范围是和获取到ViewModel传递的Lifecycle相关联。也就是说,在Lifecycle彻底消失前。ViewModel将会一直存在于内存中。

  • 对于Activity来说,是activity完成时
  • 对于fragment来说,是fragment分离时

所以基于ViewModel生命周期的特点,所以ViewModel具有下面的特点:

  • 可以避免内存泄露。在Activity.onDestroy时会关联ViewModel.onCleared()方法,从而在这里释放内存。
  • 在设备发生配置更改时(如:屏幕旋转),可以用ViewModel保存一些数据,不需要重新获取
  • 可以使用ViewModel再fragment直接共享数据(activityViewModels)
3.使用

定义ViewModel

class NameViewModel :ViewModel() {
    val currentName: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }

}

获取和使用ViewModel

class FirstFragment : Fragment() {

    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_first, container, false)
    }
	
	//	获取ViewModels
    private val model: NameViewModel by viewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val nameObserver = Observer<String> { newName ->
            textview_first.text = newName
        }
        model.currentName.observe(this, nameObserver)
        view.findViewById<Button>(R.id.button_first).setOnClickListener {
            val anotherName = "John Doe"
            //调用ViewModel
            model.currentName.setValue(anotherName)
        }
    }
}
4.ViewModel 关键类

ViewModel有两个关键的类,一个是ViewModelStore负责存储ViewModel,一个是ViewModelFactor负责生产ViewModel
所以我们看源码主要带着下面的问题看

  • ViewModelStore是如何获取到的,ViewModelStore如何存储ViewModel
  • ViewModelFactor是如何获取到的,ViewModelFactor是如何生产ViewModel
  • ViewModel的获取全链路
  • ViewModel在设备状态改变时(屏幕状态改变),如何保证数据不丢失的

二.ViewModelStore的获取

1.获取ViewModel的入口

ViewModel的入口方法:

    private val model: NameViewModel by viewModels()

进入看看实现:
FragmentViewModelLazy

@MainThread
inline fun <reified VM : ViewModel> Fragment.viewModels(
    noinline ownerProducer: () -> ViewModelStoreOwner = { this },
    //负责生产ViewModel,可以自定义实现
    noinline factoryProducer: (() -> Factory)? = null
    //ownerProducer().viewModelStore 负责存储ViewModel
) = createViewModelLazy(VM::class, { ownerProducer().viewModelStore }, factoryProducer)

2.ViewModelStore的定义

在看获取之前,我们先看看ViewModelStore的定义

public class ViewModelStore {
	//所以ViewModelStore本质就是一个hasMap
    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());
    }
    public final void clear() {
        for (ViewModel vm : mMap.values()) {
            vm.clear();
        }
        mMap.clear();
    }
}

由上面可以看出。ViewModelStore本质是一个封装的hasmap。

3.Activity中获取ViewModelStore

ownerProducer()的实现类在fragment中,我们往下看


public class ComponentActivity extends androidx.core.app.ComponentActivity {
    
    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) {
                // 从nc中恢复viewModelStore
                mViewModelStore = nc.viewModelStore;
            }
            //没有的话,重新创造一个
            if (mViewModelStore == null) {
                mViewModelStore = new ViewModelStore();
            }
        }
        return mViewModelStore;
    }
}

从源码里可以看出来,ViewModelStore优先从NonConfigurationInstances中获取,那么NonConfigurationInstances是什么呢,看下NonConfigurationInstances的定义

public class ComponentActivity extends androidx.core.app.ComponentActivity implements
    static final class NonConfigurationInstances {
        Object custom;
        ViewModelStore viewModelStore;
    }
}

NonConfigurationInstances是一个包装类,简单的将viewModelStore和custom包装了一下

我们看一下LastNonConfigurationInstance是如何获取的

public class Activity extends ContextThemeWrapper {

    public Object getLastNonConfigurationInstance() {
        return mLastNonConfigurationInstances != null
                ? mLastNonConfigurationInstances.activity : null;
    }
}

总结:最终nc就是activity.mLastNonConfigurationInstances

4.Fragment中获取ViewModelStore

ownerProducer()的实现类在fragment中,我们继续往下看

public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
        ViewModelStoreOwner, SavedStateRegistryOwner {
        ....
    @NonNull
    @Override
    public ViewModelStore getViewModelStore() {
        if (mFragmentManager == null) {
            throw new IllegalStateException("Can't access ViewModels from detached fragment");
        }
        return mFragmentManager.getViewModelStore(this);
    }
    ...
}
final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
	...
    @NonNull
    ViewModelStore getViewModelStore(@NonNull Fragment f) {
    	//这里的mNonConfig也是ViewModel是实现类
        return mNonConfig.getViewModelStore(f);
    }
    ....
}

继续往下,如何从FragmentManagerViewModel中获取ViewModelStore

//这里也是ViewModel
class FragmentManagerViewModel extends ViewModel {
 private final HashMap<String, ViewModelStore> mViewModelStores = new HashMap<>();
    @NonNull
    ViewModelStore getViewModelStore(@NonNull Fragment f) {
    	//看看是否有缓存的viewModelStore
        ViewModelStore viewModelStore = mViewModelStores.get(f.mWho);
        if (viewModelStore == null) {
        	//没有的话重新创建一个
            viewModelStore = new ViewModelStore();
            mViewModelStores.put(f.mWho, viewModelStore);
        }
        return viewModelStore;
    }
}

再看看mNonConfig(FragmentManagerViewModel)是如何创建的

final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
	
    public void attachController(@NonNull FragmentHostCallback host,
            @NonNull FragmentContainer container, @Nullable final Fragment parent) {

        // Get the FragmentManagerViewModel
        if (parent != null) {
            mNonConfig = parent.mFragmentManager.getChildNonConfig(parent);
        //如果  host是ViewModelStoreOwner
        } else if (host instanceof ViewModelStoreOwner) {
            ViewModelStore viewModelStore = ((ViewModelStoreOwner) host).getViewModelStore();
            mNonConfig = FragmentManagerViewModel.getInstance(viewModelStore);
        } else {
            mNonConfig = new FragmentManagerViewModel(false);
        }
    }
    @NonNull
    FragmentManagerViewModel getChildNonConfig(@NonNull Fragment f) {
        return mNonConfig.getChildNonConfig(f);
    }
}
class FragmentManagerViewModel extends ViewModel {
  
    static FragmentManagerViewModel getInstance(ViewModelStore viewModelStore) {
        ViewModelProvider viewModelProvider = new ViewModelProvider(viewModelStore,
                FACTORY);
        return viewModelProvider.get(FragmentManagerViewModel.class);
    }
	//获取子Fragment的FragmentManagerViewModel
    FragmentManagerViewModel getChildNonConfig(@NonNull Fragment f) {
        FragmentManagerViewModel childNonConfig = mChildNonConfigs.get(f.mWho);
        if (childNonConfig == null) {
            childNonConfig = new FragmentManagerViewModel(mStateAutomaticallySaved);
            mChildNonConfigs.put(f.mWho, childNonConfig);
        }
        return childNonConfig;
    }
}
5.小结
  • ViewModelStore本质是一个hasMap
  • 如果是在Activity中获取ViewModelStore,它会优先在activity.mLastNonConfigurationInstances中获取ViewModelStore。
  • 如果是在Fragment中获取ViewModelStore,他会从FragmentManagerViewModel中获取这个Fragment对应的ViewModelStore
  • FragmentManagerViewModel本质也是一个ViewModel,FragmentManagerViewModel是在FragmentManagerImpl.attachController()中被创建出来

三.ViewModelFactor的获取

1.获取ViewModelFactor的入口

上一节我们知道,获取ViewModel的入口,在下面
FragmentViewModelLazy

@MainThread
inline fun <reified VM : ViewModel> Fragment.viewModels(
    noinline ownerProducer: () -> ViewModelStoreOwner = { this },
    //负责生产ViewModel,可以自定义实现
    noinline factoryProducer: (() -> Factory)? = null
    //ownerProducer().viewModelStore 负责存储ViewModel
) = createViewModelLazy(VM::class, { ownerProducer().viewModelStore }, factoryProducer)

我们继续往下看
FragmentViewModelLazy

@MainThread
fun <VM : ViewModel> Fragment.createViewModelLazy(
    viewModelClass: KClass<VM>,
    storeProducer: () -> ViewModelStore,
    factoryProducer: (() -> Factory)? = null
): Lazy<VM> {
    val factoryPromise = factoryProducer ?: {
        val application = activity?.application ?: throw IllegalStateException(
            "ViewModel can be accessed only when Fragment is attached"
        )
        //获取默认的AndroidViewModelFactory
        AndroidViewModelFactory.getInstance(application)
    }
    return ViewModelLazy(viewModelClass, storeProducer, factoryPromise)
}
2.默认的ViewModelFactor - AndroidViewModelFactory

获取FragmentViewModelLazy

   public static class AndroidViewModelFactory extends ViewModelProvider.NewInstanceFactory {

        private static AndroidViewModelFactory sInstance;
		//单例
        @NonNull
        public static AndroidViewModelFactory getInstance(@NonNull Application application) {
            if (sInstance == null) {
                sInstance = new AndroidViewModelFactory(application);
            }
            return sInstance;
        }

        private Application mApplication;

        public AndroidViewModelFactory(@NonNull Application application) {
            mApplication = application;
        }

        @NonNull
        @Override
        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
            if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
                //反射获取ViewModel
                try {
                    return modelClass.getConstructor(Application.class).newInstance(mApplication);
                } catch (NoSuchMethodException e) {
                    throw new RuntimeException("Cannot create an instance of " + modelClass, e);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException("Cannot create an instance of " + modelClass, e);
                } catch (InstantiationException e) {
                    throw new RuntimeException("Cannot create an instance of " + modelClass, e);
                } catch (InvocationTargetException e) {
                    throw new RuntimeException("Cannot create an instance of " + modelClass, e);
                }
            }
            return super.create(modelClass);
        }
    }
}

3.小结
  • ViewModelFactor如果没有自定义,就会生成默认的工厂类AndroidViewModelFactory
  • AndroidViewModelFactory中ViewModel是通过反射获取ViewModel

四.ViewModel的获取

上两节我们看了存储ViewModel的ViewModelStore的获取,和一个生产ViewModel的ViewModelFactor的获取。下面我们完整的梳理一下ViewModel的获取

1.入口

FragmentViewModelLazy

@MainThread
inline fun <reified VM : ViewModel> Fragment.viewModels(
    noinline ownerProducer: () -> ViewModelStoreOwner = { this },
    //负责生产ViewModel,可以自定义实现
    noinline factoryProducer: (() -> Factory)? = null
    //ownerProducer().viewModelStore 负责存储ViewModel
) = createViewModelLazy(VM::class, { ownerProducer().viewModelStore }, factoryProducer)

我们继续往下看
FragmentViewModelLazy

@MainThread
fun <VM : ViewModel> Fragment.createViewModelLazy(
    viewModelClass: KClass<VM>,
    storeProducer: () -> ViewModelStore,
    factoryProducer: (() -> Factory)? = null
): Lazy<VM> {
    val factoryPromise = factoryProducer ?: {
        val application = activity?.application ?: throw IllegalStateException(
            "ViewModel can be accessed only when Fragment is attached"
        )
        //获取默认的AndroidViewModelFactory
        AndroidViewModelFactory.getInstance(application)
    }
    return ViewModelLazy(viewModelClass, storeProducer, factoryPromise)
}

继续往下看

class ViewModelLazy<VM : ViewModel> (
    private val viewModelClass: KClass<VM>,
    private val storeProducer: () -> ViewModelStore,
    private val factoryProducer: () -> ViewModelProvider.Factory
) : Lazy<VM> {
    private var cached: VM? = null

    override val value: VM
        get() {
            //有缓存先获取缓存
            val viewModel = cached
            return if (viewModel == null) {
                val factory = factoryProducer()
                val store = storeProducer()
                //这里获取新的ViewModel
                ViewModelProvider(store, factory).get(viewModelClass.java).also {
                    cached = it
                }
            } else {
                viewModel
            }
        }

    override fun isInitialized() = cached != null
}
2.ViewModelProvider

在ViewModelProvider获取ViewModel

public class ViewModelProvider {
    @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) {
        //优先从mViewModelStore获取ViewModel
        ViewModel viewModel = mViewModelStore.get(key);

        if (modelClass.isInstance(viewModel)) {
            //noinspection unchecked
            return (T) viewModel;
        } else {
            //noinspection StatementWithEmptyBody
            if (viewModel != null) {
                // TODO: log a warning.
            }
        }
		//如果没有就从mFactory中new一个
        if (mFactory instanceof KeyedFactory) {
            viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
        } else {
            viewModel = (mFactory).create(modelClass);
        }
        mViewModelStore.put(key, viewModel);
        //noinspection unchecked
        return (T) viewModel;
    }

}
3.小结

ViewModel的获取是在ViewModelProvider中获取的

  • ViewModel优先从ViewModelStore中获取
  • 如果mViewModelStore没有,就通过mFactory中新创建一个

五.ViewModel的恢复

上面我们完整的看完了一个viewModel的获取流程,但是我们最开始的疑问还是没有解决:

  • ViewModel在设备状态改变时(屏幕状态改变),如何保证数据不丢失的

下面我们就来看这个问题
再这之前,先回顾一个之前看代码的细节:

Activity中获取ViewModelStore,它会优先在activity.mLastNonConfigurationInstances中获取
这里的mLastNonConfigurationInstances和我们要看的内容息息相关

1.保存ViewModelStore

我们看一下,在发生设备状态改变时的回调。
ActivityThread.performDestroyActivity()

public final class ActivityThread extends ClientTransactionHandler {
    ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
            int configChanges, boolean getNonConfigInstance, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        ...
        if (r != null) {
            ....
            if (getNonConfigInstance) {
                try {
                	//保存lastNonConfigurationInstances变量
                    r.lastNonConfigurationInstances
                            = r.activity.retainNonConfigurationInstances();
                } catch (Exception e) {
                    if (!mInstrumentation.onException(r.activity, e)) {
                        throw new RuntimeException(
                                "Unable to retain activity "
                                + r.intent.getComponent().toShortString()
                                + ": " + e.toString(), e);
                    }
                }
            }
            ...
        return r;
    }
}

当设备状态发生改变时,Lifecycle状态改变为ON_DESTROY的会调

public class ComponentActivity extends androidx.core.app.ComponentActivity {
    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();
                    }
                }
            }
        });
    }

}
  
2.恢复ViewModelStore

当配置更改发生后,如何再次恢复
ActivityThread.performLaunchActivity

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ActivityInfo aInfo = r.activityInfo;
        ...
        
        try {
            	...
            	//这里我们可以看到,将lastNonConfigurationInstances传入activity中
                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);

                ...
        } catch (SuperNotCalledException e) {
            ...

        } catch (Exception e) {
           ...
        }

        return activity;
    }

attach方法

    @UnsupportedAppUsage
    final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
        attachBaseContext(context);

	      .....
	     //完成赋值
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
	    ....
    }
3.小结

ViewModel的恢复其实本质就是在配置信息发生改变后,在activity销毁前,将其ViewModelStore保存,并且判断时重建时不清空ViewModelStore,然后再activity重建后,将ViewModelStore恢复,去出ViewModelStore中的ViewModel。

4.其他

资源不足,或者后台进程关闭后所导致的activity被回收,viewModel是否可以将数据恢复
答:不可以,但是可以支持

使用SavedStateHandle

六.ViewModel与SavedStateHandle

1.SavedStateHandle的介绍

我们知道如果资源不足,或者后台进程关闭后所导致的activity被回收,viewModel是不可以将数据恢复。如果此时想让数据恢复,我们就要引入SavedStateHandle

在这里插入图片描述
所以onSaveInstanceState方法能保存的数据的场景:

  • 由于资源限制,Activity被系统杀掉;
  • 配置更改。

onSaveInstanceState特点:
onSaveInstanceState方法只能保存少量简单的数据,大量和复杂数据最后不要放在onSaveInstanceState方法保存。因为onSaveInstanceState方法是通过Bundle保存数据,如果数据的量太大或者太复杂,会阻塞UI线程,从而影响Activity生命周期的执行。

2.SavedStateHandle的使用

SavedStateHandle的使用比较简单
定义ViewModerl

class NameWithSaveViewModel(private  val saveStateHandle: SavedStateHandle) :ViewModel() {
    // 需要在资源限制导致重建的场景下保存的数据
    // 用LiveData暴露,不能让外部直接通过LiveData去修改内部的值
    val mAgeLiveData: LiveData<Int> = saveStateHandle.getLiveData(KEY_AGE)
    
    fun setAge(age: Int) {
        saveStateHandle.set(KEY_AGE, age)
    }

    companion object {
        const val KEY_AGE = "key_age";
    }

}

创建ViewModel对下,使用VeiwModel

class FirstFragment : Fragment() {

    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_first, container, false)
    }
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
		
		//创建Viewmodel
        val viewModel = ViewModelProvider(
            this,
            SavedStateViewModelFactory(activity?.application, this)
        )[NameWithSaveViewModel::class.java]
      
        view.findViewById<Button>(R.id.button_first).setOnClickListener {
            //保存数据
            viewModel.setAge(1)
        }
    }
}

3.SavedStateHandle相关类

和SavedStateHandle 相关有四个类,SavedStateRegistryOwner,SavedStateRegistryController,SavedStateRegistry,SavedStateProvider。

我们分别看看这四个类的作用

  • SavedStateRegistryOwner: 接口,有一个getSavedStateRegistry方法,作用是提供SavedStateRegistry对象。该接口主要实现类有Activity和Fragment。
  • SavedStateRegistryController: SavedStateRegistry的控制类,主要有两个方法:performRestore方法的作用恢复数据;performSave方法主要保存数据。Activity和Fragment直接操作类就是该类。
  • SavedStateRegistry:主要是从Activity或者Fragment等)恢复数据,或者需要保存的数据写入UI控制器的Bundle里面。SavedStateRegistryController主要操作类就是该类。
  • SavedStateProvider: 主要是提供保存和恢复的数据。该接口只有一个saveState方法,主要的作用将需要保存的数据用Bundle包装起来。
    在这里插入图片描述
    我们在ComponentActivity看看SavedStateHandle如何工作的
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        LifecycleOwner,
        ViewModelStoreOwner,
        SavedStateRegistryOwner, 
        OnBackPressedDispatcherOwner {
	
	private final SavedStateRegistryController mSavedStateRegistryController =
            SavedStateRegistryController.create(this)// ······
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mSavedStateRegistryController.performRestore(savedInstanceState);
        // ······
    }
 
    @CallSuper
    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        // ······
        mSavedStateRegistryController.performSave(outState);
    }
    // ······

	
}

从上面的代码我们可以看出来:SavedStateRegistryController主要分为两个过程:

  • 在onCreate方法调用了performRestore方法,主要的作用是恢复已保存的数据。
  • 在onDestroy方法调用了performSave方法,主要的作用保存数据。
4.SavedStateHandle保存数据

入口代码:

mSavedStateRegistryController.performSave(outState);

SavedStateRegistryController中

public final class SavedStateRegistryController {
    private final SavedStateRegistryOwner mOwner;
    private final SavedStateRegistry mRegistry;
    @MainThread
    public void performSave(@NonNull Bundle outBundle) {
        mRegistry.performSave(outBundle);
    }
}

在SavedStateRegistr中

public final class SavedStateRegistry {
    @MainThread
    void performSave(@NonNull Bundle outBundle) {
        Bundle components = new Bundle();
        if (mRestoredState != null) {
            components.putAll(mRestoredState);
        }
        //SavedStateProvider
        for (Iterator<Map.Entry<String, SavedStateProvider>> it =
                mComponents.iteratorWithAdditions(); it.hasNext(); ) {
            Map.Entry<String, SavedStateProvider> entry1 = it.next();
            //saveState需要保存的数据
            components.putBundle(entry1.getKey(), entry1.getValue().saveState());
        }
        outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
    }
}

SavedStateProvider定义

    public interface SavedStateProvider {
        @NonNull
        Bundle saveState();
    }
  • 如果mRestoredState不为空,表示之前恢复的数据还没有被消费完,需要将没有消费的数据再一次保存。
  • 遍历所有注册的SavedStateProvider,将所有的SavedStateProvider提供的数据保存起来。
  • 将所有保存的数据全部写入到Activity的Bundle对象。
5.SavedStateHandle恢复数据

入口代码

     mSavedStateRegistryController.performRestore(savedInstanceState);

SavedStateRegistryController中

public final class SavedStateRegistryController {
    private final SavedStateRegistryOwner mOwner;
    private final SavedStateRegistry mRegistry;
    @MainThread
    public void performRestore(@Nullable Bundle savedState) {
        Lifecycle lifecycle = mOwner.getLifecycle();
        if (lifecycle.getCurrentState() != Lifecycle.State.INITIALIZED) {
            throw new IllegalStateException("Restarter must be created only during "
                    + "owner's initialization stage");
        }
        lifecycle.addObserver(new Recreator(mOwner));
        mRegistry.performRestore(lifecycle, savedState);
    }

}

在SavedStateRegistr中

public final class SavedStateRegistry {
    @MainThread
    void performRestore(@NonNull Lifecycle lifecycle, @Nullable Bundle savedState) {
        if (mRestored) {
            throw new IllegalStateException("SavedStateRegistry was already restored.");
        }
        if (savedState != null) {
        	//恢复数据
            mRestoredState = savedState.getBundle(SAVED_COMPONENTS_KEY);
        }

        lifecycle.addObserver(new GenericLifecycleObserver() {
            @Override
            public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
                if (event == Lifecycle.Event.ON_START) {
                    mAllowingSavingState = true;
                } else if (event == Lifecycle.Event.ON_STOP) {
                    mAllowingSavingState = false;
                }
            }
        });

        mRestored = true;
    }
}

目前是将数据保持在mRestoredState,但并没有给ViewModel。什么时候赋值给ViewMoedl,我们换个角度看看,从VIewModel的重新创建看起。在SavedStateHandle场景中,ViewModel的工厂类是SavedStateViewModelFactory。我们看看此时ViewModel的创建

public final class SavedStateViewModelFactory extends ViewModelProvider.KeyedFactory {

    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) {
        boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
        Constructor<T> constructor;
        //获取viewmodel的modelClass
        if (isAndroidViewModel && mApplication != null) {
            constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
        } else {
            constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
        }
		...
		//创建controller
        SavedStateHandleController controller = SavedStateHandleController.create(
                mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
        try {
            T viewmodel;
            if (isAndroidViewModel && mApplication != null) {
      			//创建viewmodel对象
                viewmodel = constructor.newInstance(mApplication, controller.getHandle());
            } else {
                viewmodel = constructor.newInstance(controller.getHandle());
            }
            viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
            return viewmodel;
        } catch (IllegalAccessException e) {
         	...
        }
    }
 }

我们看看SavedStateHandleController中做了什么

final class SavedStateHandleController implements LifecycleEventObserver {
    static SavedStateHandleController create(SavedStateRegistry registry, Lifecycle lifecycle,
            String key, Bundle defaultArgs) {
        //获取之前保存的Bundle    
        Bundle restoredState = registry.consumeRestoredStateForKey(key);
        SavedStateHandle handle = SavedStateHandle.createHandle(restoredState, defaultArgs);
        SavedStateHandleController controller = new SavedStateHandleController(key, handle);
        //将SavedStateHandle的SavedStateProvider注册到SavedStateRegistry
        controller.attachToLifecycle(registry, lifecycle);
        tryToAddRecreator(registry, lifecycle);
        return controller;
    }

 }

在SavedStateRegistr中

public final class SavedStateRegistry {
    public Bundle consumeRestoredStateForKey(@NonNull String key) {
        if (!mRestored) {
            throw new IllegalStateException("You can consumeRestoredStateForKey "
                    + "only after super.onCreate of corresponding component");
        }
        if (mRestoredState != null) {
            Bundle result = mRestoredState.getBundle(key);
            mRestoredState.remove(key);
            if (mRestoredState.isEmpty()) {
                mRestoredState = null;
            }
            //返回恢复的Bundle
            return result;
        }
        return null;
    }
}

小结:
1.在activityd的onCreate 通过SavedStateHandleController恢复之前保持的数据
2.在SavedStateHandle场景中,ViewModel的工厂类是SavedStateViewModelFactory,此时ViewModel通过SavedStateViewModelFactory创建
3.在ViewModel的create中通过SavedStateHandleController获得之前保存的数据
4.ViewModel根据之前获得的数据,通过反射方式创建一个新的ViewModel

七.参考资料

ViewModel源码,学起来!

JetPack之ViewModel源码解析

官方文档

Android Jetpack是Google提供的一套用于加速Android应用开发的工具包,其中包括了许多架构组件,其中之一就是ViewModelViewModel是一种设计模式,用于保存和管理与UI相关的数据。在传统的Android开发中,当屏幕旋转或者因为其他原因导致Activity或Fragment重建时,之前保存的临时数据就会丢失。而ViewModel的出现解决了这个问题。 ViewModel的主要作用是将数据与UI组件分离。它的工作方式是创建一个ViewModel类,并在其中保存需要与UI组件交互的数据。这样,当屏幕旋转或重建时,ViewModel实例不会销毁,数据也会得到保留。然后,在Activity或Fragment中,通过获取ViewModel实例,可以轻松地访问这些数据。 使用ViewModel的好处有很多。首先,它可以避免内存泄漏,因为ViewModel的生命周期与Activity或Fragment无关。其次,它可以节省资源,因为当Activity或Fragment销毁时,ViewModel实例可以被系统缓存起来,下次再创建时可以直接返回该实例。另外,由于ViewModel保存了与UI相关的数据,可以减少因为屏幕旋转导致的数据重复加载的问题。 在使用ViewModel时,你可以选择使用Android Jetpack中的其他架构组件来进一步提高开发效率,比如通过LiveData实现数据的观察和通知,或者通过DataBinding来实现UI与数据的自动绑定。 总之,ViewModelAndroid Jetpack中非常重要的一个架构组件,它的出现实现了数据与UI的解耦,提高了开发效率,并且解决了数据丢失的问题。希望通过这篇文档的详解,你对ViewModel有了更深入的理解。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值