Android源码解析:ViewModel

ViewModel 是 Android 架构组件之一,用于分离 UI 逻辑与 UI 数据。在发生 Configuration Changes 时,它不会被销毁。在界面重建后,方便开发者呈现界面销毁前的 UI 状态。

主要类

ViewModel主要类图.png
  1. ViewModel
    ViewModel 是一个抽象类,只定义了一个空的 onCleared()方法。
    AndroidViewModel 类扩展了 ViewModel 类,增加了Application 字段,在构造方法初始化,并提供了 getApplication() 方法。
public abstract class ViewModel {
    protected void onCleared() {
    }
}
// AndroidViewModel继承ViewModel,持有Application
public class AndroidViewModel extends ViewModel {
    private Application mApplication;
    public AndroidViewModel(@NonNull Application application) {
        mApplication = application;
    }
    public <T extends Application> T getApplication() {
        return (T) mApplication;
    }
}
  1. ViewModelProviders
    ViewModelProviders 类提供了4个静态工厂方法 of() 创建一个新的 ViewModelProvider 对象。
public class ViewModelProviders {
    public static ViewModelProvider of(@NonNull Fragment fragment) {
        return of(fragment, null);
    }

    public static ViewModelProvider of(@NonNull FragmentActivity activity) {
        return of(activity, null);
    }

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

    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);
    }
  1. ViewModelProvider
    ViewModelProvider 负责提供 ViewModel 对象
public class ViewModelProvider {
    private final Factory mFactory;
    private final ViewModelStore mViewModelStore;
    //获取一个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);
    }
  //从ViewModelStore中获取ViewModel
   public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> 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;
    }
  1. Factory
    创建ViewModel工厂的接口类
 public interface Factory {
        <T extends ViewModel> T create(@NonNull Class<T> modelClass);
    }
  1. ViewModelStore
    使用Map存储当前页面已存在的ViewModel
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);
    }
    public final void clear() {
        for (ViewModel vm : mMap.values()) {
            vm.onCleared();
        }
        mMap.clear();
    }
}

ViewModelStore 是来自于 FragmentActivity 和 Fragment,它们实现了 ViewModelStoreOwner 接口,返回当前 UI 作用域里的 ViewModelStore 对象。

   public ViewModelStore getViewModelStore() {
        if (getContext() == null) {
            throw new IllegalStateException("Can't access ViewModels from detached fragment");
        }
        if (mViewModelStore == null) {
            mViewModelStore = new ViewModelStore();
        }
        return mViewModelStore;
    }
    public void onDestroy() {
        mCalled = true;
        FragmentActivity activity = getActivity();
        boolean isChangingConfigurations = activity != null && activity.isChangingConfigurations();
        if (mViewModelStore != null && !isChangingConfigurations) {
            mViewModelStore.clear();
        }
    }

当 Activity 或 Fragment 被系统重建时,ViewModel 对象不会被销毁,新的 Activity 或 Fragment 对象拿到的是同一个 ViewModel 对象。
在 FragmentActivity#onRetainNonConfigurationInstance() 方法中,会将 ViewModelStore 对象保留起来。然后在 onCreate() 方法能获取之前保留起来的 ViewModelStore 对象。

    public final Object onRetainNonConfigurationInstance() {
        Object custom = onRetainCustomNonConfigurationInstance();

        FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();

        if (fragments == null && mViewModelStore == null && custom == null) {
            return null;
        }

        NonConfigurationInstances nci = new NonConfigurationInstances();
        nci.custom = custom;
        nci.viewModelStore = mViewModelStore;
        nci.fragments = fragments;
        return nci;
    }
   protected void onCreate(@Nullable Bundle savedInstanceState) {
        NonConfigurationInstances nc =
                (NonConfigurationInstances) getLastNonConfigurationInstance();
        if (nc != null && nc.viewModelStore != null && mViewModelStore == null) {
            mViewModelStore = nc.viewModelStore;
        }
}     

总结:

  • 通过 ViewModelProviders 创建 ViewModelProvider 对象,调用ViewModelProvider的 get() 方法获取 ViewModel 对象。 当 ViewModelStore 里不存在想要的对象,ViewModelProvider 会使用 Factory 新建一个对象并存放到 ViewModelStore 里。
  • 当发生 发生 Configuration Changes 时,FragmentActivity 利用 getLastNonConfigurationInstance()、onRetainNonConfigurationInstance() 方法实现 ViewModelStore 的保留与恢复,进而实现 ViewModel 对象的保活。
  • 当 FragmentActivity 和 Fragment 被销毁时,会根据是否发生 Configuration Changes 来决定是否销毁 ViewModel

参考文献:
1、源码解析Android架构组件ViewModel
2、剖析 Android 架构组件之 ViewModel
3、Android Jetpack架构组件之 ViewModel

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容