Android ViewModel 超详细分析

ViewModel 的意义

ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。ViewModel 负责为 Activity 或 Fragment 准备和管理数据,并处理 Activity / Fragment 与应用程序其余部分的通信(例如调用业务逻辑类)。

ViewModel 的目的是获取和保存 Activity 或 Fragment 所需的信息。Activity 或 Fragment 应当能够观察到 ViewModel 的变化。ViewModel 通常通过 LiveData 或 Android 数据绑定公开这些信息。您还可以使用您喜欢的框架中的任何可观察性构造。

ViewModel 的特点

ViewModel 始终与具有生命周期的组件(Activity 或 Fragment)关联创建,并且只要组件仍处于活跃状态就会保留数据。换句话说,这意味着如果 ViewModel 的持有者因配置更改(例如旋转)而被销毁,则不会销毁 ViewModel。新的持有者实例只是重新关联到现有的 ViewModel。

ViewModel 的唯一职责是管理 UI 的数据。它永远不应访问您的视图层次结构或保留对 Activity 或 Fragment 的引用。

为什么需要 ViewModel

Android 框架可以管理界面控制器(如 Activity 和 Fragment)的生命周期。Android 框架可能会决定销毁或重新创建界面控制器,以响应完全不受您控制的某些用户操作或设备事件。

如果系统销毁或重新创建界面控制器,则存储在其中的任何瞬态界面相关数据都会丢失。例如,应用可能会在它的某个 Activity 中包含用户列表。为配置更改重新创建 Activity 后,新 Activity 必须重新提取用户列表。对于简单的数据,activity 可以使用 onSaveInstanceState() 方法从 onCreate() 中的捆绑包恢复其数据,但此方法仅适合可以序列化再反序列化的少量数据,而不适合数量可能较大的数据,如用户列表或位图。

另一个问题是,界面控制器经常需要进行可能需要一些时间才能返回的异步调用。界面控制器需要管理这些调用,并确保系统在其销毁后清理这些调用以避免潜在的内存泄漏。此项管理需要大量的维护工作,并且在为配置更改重新创建对象的情况下,会造成资源的浪费,因为对象可能需要重新发出已经发出过的调用。

诸如 Activity 和 Fragment 之类的界面控制器主要用于显示界面数据、对用户操作做出响应或处理操作系统通信(如权限请求)。如果要求界面控制器也负责从数据库或网络加载数据,那么会使类越发膨胀。为界面控制器分配过多的责任可能会导致单个类尝试自己处理应用的所有工作,而不是将工作委托给其他类。以这种方式为界面控制器分配过多的责任也会大大增加测试的难度。

从界面控制器逻辑中分离出视图数据所有权的操作更容易且更高效。

ViewModel 的使用

下面是一个在 Activity 中使用 ViewModel 的示例代码:

  // ViewModel
   public class UserModel extends ViewModel {
       private final MutableLiveData<User> userLiveData = new MutableLiveData<>();
  
       public LiveData<User> getUser() {
           return userLiveData;
       }
  
       public UserModel() {
           // trigger user load.
       }
  
       void doAction() {
           // depending on the action, do necessary business logic calls and update the
           // userLiveData.
       }
   }

在 Activity 中使用:

   public class UserActivity extends Activity {
  
        @Override
       protected void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.user_activity_layout);
           final UserModel viewModel = new ViewModelProvider(this).get(UserModel.class);
           viewModel.getUser().observe(thisnew Observer<User>() {
                @Override
               public void onChanged(@Nullable User data) {
                   // update ui.
               }
           });
           findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
                @Override
               public void onClick(View v) {
                    viewModel.doAction();
               }
           });
       }
   }

ViewModel 也可以用作 Activity 的不同 Fragment 之间的通信层。每个 Fragment 都可以通过它们的 Activity 使用相同的键获取 ViewModel。这允许 Fragment 之间以解耦的方式进行通信,这样它们就不需要直接与另一个 Fragment 对话。

   public class MyFragment extends Fragment {
       public void onStart() {
           UserModel userModel = new ViewModelProvider(requireActivity()).get(UserModel.class);
       }
   }

ViewModel 的原理

ViewModel 类源码

ViewModel 是一个抽象类:

public abstract class ViewModel

内部属性有两个:

    // Can't use ConcurrentHashMap, because it can lose values on old apis (see b/37042460)
    @Nullable
    private final Map<String, Object> mBagOfTags = new HashMap<>();
    private volatile boolean mCleared = false;
  • mBagOfTags :以 key-value 的形式保存数据。
  • mCleared :用来作为标志位,在 clear 方法中使用。

mBagOfTags 对于数据的存储和移除逻辑:

    <T> getTag(String key) {
        if (mBagOfTags == null) {
            return null;
        }
        synchronized (mBagOfTags) {
            return (T) mBagOfTags.get(key);
        }
    }

设置 Tag :

    <T> setTagIfAbsent(String key, T newValue) {
        T previous;
        synchronized (mBagOfTags) {
            previous = (T) mBagOfTags.get(key);
            if (previous == null) {
                mBagOfTags.put(key, newValue);
            }
        }
        T result = previous == null ? newValue : previous;
        if (mCleared) {
            // 正在清理数据(clear())时会抛出异常
            closeWithRuntimeException(result);
        }
        return result;
    }

检查对象类型是否为 Closeable ,是的话执行 close 方法:

    private static void closeWithRuntimeException(Object obj) {
        if (obj instanceof Closeable) {
            try {
                ((Closeable) obj).close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

而对于清除数据,方法为 clear()

    @MainThread
    final void clear() {
        mCleared = true
        if (mBagOfTags != null) {
            synchronized (mBagOfTags) {
                for (Object value : mBagOfTags.values()) {
                    closeWithRuntimeException(value);
                }
            }
        }
        onCleared();
    }

onCleared 是一个空方法,供子类去实现:

   protected void onCleared() {
   }

这就是 ViewModel 类的所有代码了。

ViewModelProvider.KeyedFactory

分析完 ViewModel 中的代码,我们知道有一个 Map 来保存数据,那么它的 setTagIfAbsent 方法是在哪里调用的呢?

查看这个方法的调用栈发现,调用 setTagIfAbsent 方法的类有两个:

  1. SavedStateViewModelFactory
  2. AbstractSavedStateViewModelFactory

它们都来自于

androidx.lifecycle:lifecycle-viewmodel-savedstate

注意⚠️:在一些老项目中需要引用 lifecycle 相关的依赖。

看一眼 SavedStateViewModelFactory 的注释:

ViewModelProvider.Factory 可以创建 ViewModel,通过在构造函数中接收的 SavedStateHandle 访问和提供的保存状态。如果将 defaultArgs 包传递给构造函数,它将在 SavedStateHandle 中提供默认值。如果 ViewModel 是 AndroidViewModel 的实例,它会查找接收 Application 和 SavedStateHandle 的构造函数(按此顺序),否则它会查找仅接收 SavedStateHandle 的构造函数。仅当您传递非空 Application 实例时才支持 AndroidViewModel。

再看一眼 AbstractSavedStateViewModelFactory 的:

为每个请求的 ViewModel 创建 SavedStateHandle 的 androidx.lifecycle.ViewModelProvider.KeyedFactory 的骨架。子类实现 create(String, Class, SavedStateHandle) 以实际实例化 androidx.lifecycle.ViewModels。

Anyway,这两个类都是继承自 ViewModelProvider.KeyedFactory ,那么就去看看这个接口有什么作用:

Factory 接口的实现负责实例化 ViewModel。这是 ViewModelProvider.Factory 的更高级版本,它接收为请求的 ViewModel 指定的密钥。

    abstract static class KeyedFactory extends OnRequeryFactory implements Factory {
        /**
         * 创建给定 {@code Class} 的新实例。
         *
         * @param key 与请求的 ViewModel 关联的 key
         * @param modelClass 请求实例的 {@code Class}
         * @param <T>        ViewModel 的类型参数。
         * @return 一个新创建的 ViewModel
         */

        @NonNull
        public abstract <T extends ViewModel> create(@NonNull String key, @NonNull Class<T> modelClass);

        @NonNull
        @Override
        public <T extends ViewModel> create(@NonNull Class<T> modelClass) {
            throw new UnsupportedOperationException("create(String, Class<?>) must be called on "
                    + "implementaions of KeyedFactory");
        }
    }

这个意思是通过 create 方法可以创建新的 ViewModel 实例。

简单过一下两个实现对于 create 方法的实现,AbstractSavedStateViewModelFactory 的 create 方法是需要子类去实现的:

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@NonNull
@Override
public final <T extends ViewModel> create(@NonNull String key, @NonNull Class<T> modelClass) {
    SavedStateHandleController controller = SavedStateHandleController.create(
            mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
    T viewmodel = create(key, modelClass, controller.getHandle());
    viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
    return viewmodel;
}

@NonNull
protected abstract <T extends ViewModel> create(@NonNull String key,
        @NonNull Class<T> modelClass, @NonNull SavedStateHandle handle)
;

而 SavedStateViewModelFactory 的实现是通过反射创建的对象:

@NonNull
@Override
public <T extends ViewModel> create(@NonNull String key, @NonNull Class<T> modelClass) {
    boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
    Constructor<T> constructor;
    if (isAndroidViewModel && mApplication != null) {
        constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
    } else {
        constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
    }
    // doesn't need SavedStateHandle
    if (constructor == null) {
        return mFactory.create(modelClass);
    }

    SavedStateHandleController controller = SavedStateHandleController.create(mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
    try {
        T viewmodel;
        if (isAndroidViewModel && mApplication != null) {
            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) {
        throw new RuntimeException("Failed to access " + modelClass, e);
    } catch (InstantiationException e) {
        throw new RuntimeException("A " + modelClass + " cannot be instantiated.", e);
    } catch (InvocationTargetException e) {
        throw new RuntimeException("An exception happened in constructor of " + modelClass, e.getCause());
    }
}

查找构造器的方法:

@SuppressWarnings("unchecked")
private static <T> Constructor<T> findMatchingConstructor(Class<T> modelClass,
        Class<?>[] signature)
 
{
    for (Constructor<?> constructor : modelClass.getConstructors()) {
        Class<?>[] parameterTypes = constructor.getParameterTypes();
        if (Arrays.equals(signature, parameterTypes)) {
            return (Constructor<T>) constructor;
        }
    }
    return null;
}

而不管是哪个方法它们设置的 Tag 都是 TAG_SAVED_STATE_HANDLE_CONTROLLER :

    static final String TAG_SAVED_STATE_HANDLE_CONTROLLER = "androidx.lifecycle.savedstate.vm.tag";

再回过头来看 KeyedFactory , 它是 ViewModelProvider 的内部抽象类,它的继承关系是:

abstract static class KeyedFactory extends OnRequeryFactory implements Factory

KeyedFactory 中定义的方法在上文中分析过,这里去查看它的父类型都做了什么,首先是 Factory 接口:

public interface Factory {
    @NonNull
    <T extends ViewModel> create(@NonNull Class<T> modelClass);
}

Factory 接口的实现负责实例化 ViewModel。

OnRequeryFactory 类:

static class OnRequeryFactory {
    void onRequery(@NonNull ViewModel viewModel) {
    }
}

OnRequeryFactory 中定义了一个 onRequery 方法,用来表示具备重新查询的能力。

ViewModelProvider 获取 ViewModel

分析到这里,回过头看 ViewModel 的创建:

ViewModelProvider(this).get(CheckViewModel::class.Java)

ViewModelProvider 的初始化先不看,后面再分析,先看看它的 get 方法:

@NonNull
@MainThread
public <T extends ViewModel> get(@NonNull Class<T> modelClass) {
    String canonicalName = modelClass.getCanonicalName();
    if (canonicalName == null) {
        throw new IllegalArgumentException("局部类和匿名类不能作为 ViewModel");
    }
    return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}

这是一个路由方法,它对 ViewModel 做了两个要求:

  1. get 方法只能在主线程运行
  2. ViewModel 不能是局部类和匿名类

然后调用 get(@*NonNull* *String* key, @*NonNull* *Class*<T> modelClass) ,Key 是根据 ViewModel 类型 + 一个前缀:

private static final String DEFAULT_KEY = "androidx.lifecycle.ViewModelProvider.DefaultKey";
@NonNull
@MainThread
public <T extends ViewModel> 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;
}

在这个方法中:

  1. 首先通过 mViewModelStore 通过 key 查找并获取 ViewModel 对象
  2. 检查 viewModel 的类型是否是 get 参数期待获取的类型
    1. 若是,检查 mFactory 是不是 OnRequeryFactory 类型,是则调用 onRequery 方法处理 viewModel ,并返回 viewModel 对象。
  3. 检查 mFactory 是否是 KeyedFactory 类型
    1. 若是,调用 create 方法重新创建 ViewModel
    2. 否则调用自身 Factory 中定义的 create 方法,创建 ViewModel
  4. 然后将新的 viewModel 对象和 key 以键值对的形式保存到 mViewModelStore
  5. 最后返回 viewModel 对象

逐步分析,首先是在创建 ViewModel 对象前,优先去 mViewModelStore 对象中查找,并且在创建逻辑完成后,将新的 ViewModel 对象保存到 mViewModelStore 对象中。mViewModelStore 看起来是一个缓存机制,它的类型是 ViewModelStore 。在稍后我们再分析这个类。

当我们从 ViewModelStore 中取出的 ViewModel 对象是我们尝试获取的类型时,开始使用 mFactory 来处理 ViewModel 对象,mFactory 的定义是:

private final Factory mFactory;

而它的初始化,则是在 ViewModelProvider 的构造函数中,接下来就顺便分析 ViewModelProvider 的初始化流程。

ViewModelProvider 的创建

回顾 ViewModel 的创建:

ViewModelProvider(this).get(CheckViewModel::class.java)

从这行代码可以看出 ViewModelProvider 是通过一个参数的构造函数进行创建的:

public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
    this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
            ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
            : NewInstanceFactory.getInstance());
}

单个参数的构造方法调用了参数类型为 ViewModelStore, Factory 的构造方法:

public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
    mFactory = factory;
    mViewModelStore = store;
}

而这两个参数分别是:

  • owner.getViewModelStore()
  • 根据 owner 类型是不是 HasDefaultViewModelProviderFactory
    • 是,HasDefaultViewModelProviderFactory.getDefaultViewModelProviderFactory()
    • 否,NewInstanceFactory.getInstance()

ViewModelStore 这个后续分析,先看看 Factory 到底是什么。

HasDefaultViewModelProviderFactory

public interface HasDefaultViewModelProviderFactory {
    @NonNull
    ViewModelProvider.Factory getDefaultViewModelProviderFactory();
}

NewInstanceFactory

NewInstanceFactory 是 ViewModelProvider 的静态内部类:

public static class NewInstanceFactory implements Factory {

    private static NewInstanceFactory sInstance;

    @NonNull
    static NewInstanceFactory getInstance() {
        if (sInstance == null) {
            sInstance = new NewInstanceFactory();
        }
        return sInstance;
    }

    @SuppressWarnings("ClassNewInstance")
    @NonNull
    @Override
    public <T extends ViewModel> create(@NonNull Class<T> modelClass) {
        //noinspection TryWithIdenticalCatches
        try {
            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);
        }
    }
}

逻辑很清晰,一个单例模式,create 方法中直接通过反射 API 创建一个无参实例。很显然,这个 Factory 不是 OnRequeryFactory 的实现。

SavedStateViewModelFactory

那么还记得 OnRequeryFactory 的实现是什么吗?是 ViewModelProvider.KeyedFactory ,而它的实现又有 SavedStateViewModelFactory 和 AbstractSavedStateViewModelFactory 。

SavedStateViewModelFactory 和 AbstractSavedStateViewModelFactory 的 onRequery 方法是一样的:

// in AbstractSavedStateViewModelFactory  
// in SavedStateViewModelFactory 
import static androidx.lifecycle.SavedStateHandleController.attachHandleIfNeeded;

@Override
void onRequery(@NonNull ViewModel viewModel) {
    attachHandleIfNeeded(viewModel, mSavedStateRegistry, mLifecycle);
}

// in SavedStateHandleController
static void attachHandleIfNeeded(ViewModel viewModel, SavedStateRegistry registry, Lifecycle lifecycle) {
    SavedStateHandleController controller = viewModel.getTag(TAG_SAVED_STATE_HANDLE_CONTROLLER);
    if (controller != null && !controller.isAttached()) {
        controller.attachToLifecycle(registry, lifecycle);
        tryToAddRecreator(registry, lifecycle);
    }
}

SavedStateHandleController

onRequery 方法的代码中涉及到了一个关键的 SavedStateHandleController 。它的作用还要从 ComponentActivity 说起。

ComponentActivity 中的 onSaveInstanceState 方法会触发 ViewModel 保存数据:

protected void onSaveInstanceState(@NonNull Bundle outState) {
    Lifecycle lifecycle = getLifecycle();
    if (lifecycle instanceof LifecycleRegistry) {
        ((LifecycleRegistry) lifecycle).setCurrentState(Lifecycle.State.CREATED);
    }
    super.onSaveInstanceState(outState);
   // 关键的一行
    mSavedStateRegistryController.performSave(outState); 
    mActivityResultRegistry.onSaveInstanceState(outState);
}

这里实质上就是通过 mSavedStateRegistryController 对象来保存 Bundle 的:

mSavedStateRegistryController.performSave(outState); 

mSavedStateRegistryController 的类型是 SavedStateRegistryController ,ComponentActivity 保存和恢复数据的逻辑都通过 SavedStateRegistryController 来处理。

@MainThread
public void performSave(@NonNull Bundle outBundle) {
    mRegistry.performSave(outBundle);
}

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

而 SavedStateRegistryController 又将逻辑交给 mRegistry 去处理。mRegistry 的类型是 SavedStateRegistry ,在 mSavedStateRegistryController 的构造方法中初始化:

private SavedStateRegistryController(SavedStateRegistryOwner owner) {
    mOwner = owner;
    mRegistry = new SavedStateRegistry();
}

SavedStateRegistry

SavedStateRegistry 处理保存的逻辑是:

@MainThread
void performSave(@NonNull Bundle outBundle) {
    Bundle components = new Bundle();
    if (mRestoredState != null) { // 将恢复数据全部保存到新的 bundle
        components.putAll(mRestoredState);
    }
    for (Iterator<Map.Entry<String, SavedStateProvider>> it = mComponents.iteratorWithAdditions(); it.hasNext(); ) {
        Map.Entry<String, SavedStateProvider> entry1 = it.next();
        components.putBundle(entry1.getKey(), entry1.getValue().saveState());
    }
    outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
}

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

SavedStateRegistry 中,本质上是对 Bundle 的恢复和保存逻辑。

至此,ViewModelProvider 的创建和 Factory 都已经清晰明了了。我们在回顾一下 get 方法中的逻辑:

  1. 首先通过 mViewModelStore 通过 key 查找并获取 ViewModel 对象
  2. 检查 viewModel 的类型是否是 get 参数期待获取的类型
    1. 若是,检查 mFactory 是不是 OnRequeryFactory 类型,是则调用 onRequery 方法处理 viewModel ,并返回 viewModel 对象。
  3. 检查 mFactory 是否是 KeyedFactory 类型
    1. 若是,调用 create 方法重新创建 ViewModel
    2. 否则调用自身 Factory 中定义的 create 方法,创建 ViewModel
  4. 然后将新的 viewModel 对象和 key 以键值对的形式保存到 mViewModelStore
  5. 最后返回 viewModel 对象

分析完 SavedStateRegistry 后,执行 onRequery 方法的步骤的作用就是用来恢复数据的。修改这个步骤说明:

  1. 首先从 ViewModelStore 通过 key 查找并获取 ViewModel 对象
  2. 检查 ViewModel 的类型是否与尝试使用 get 获取的类型一致
    1. 若是,检查 mFactory 是不是 OnRequeryFactory 类型,是则调用 onRequery 方法将之前保存的 Bundle 数据保存到 ViewModel 中,并返回 ViewModel 对象。
  3. 检查 mFactory 是否是 KeyedFactory 类型
    1. 若是,调用 create 方法,通过键值对的形式创建 ViewModel
    2. 否则调用自身 Factory 中定义的 create 方法,直接创建 ViewModel
  4. 然后将新的 ViewModel 对象和 key 以键值对的形式保存到 mViewModelStore
  5. 最后返回 ViewModel 对象

这样看来还剩下 ViewModelStore 没有分析,但在分析 ViewModelStore 之前,需要分析一下相关的一些类。

ViewModelStoreOwner

ViewModelStoreOwner 是一个接口,具备获取一个 ViewModelStore 的能力。

public interface ViewModelStoreOwner {
    @NonNull
    ViewModelStore getViewModelStore();
}

它的实现包括:

  • androidx.fragment.app.Fragment
  • androidx.activity.ComponentActivity

这里在一定程度上说明 ViewModel 仅支持 Fragment 和 Activity 这种实现了 ViewModelStoreOwner 接口的类。

ComponentActivity

ComponentActivity 的子类是 FragmentActivity ,是 AppCompatActivity 父类型中的一环。

ComponentActivity 中有一个 mViewModelStore 属性:

private ViewModelStore mViewModelStore;

因为实现了 ViewModelStoreOwner,所以需要实现 getViewModelStore 方法:

@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.");
    }
    ensureViewModelStore();
    return mViewModelStore;
}

ensureViewModelStore 方法确保创建了 mViewModelStore 对象:

void ensureViewModelStore() {
    if (mViewModelStore == null) {
        NonConfigurationInstances nc =
                (NonConfigurationInstances) getLastNonConfigurationInstance();
        if (nc != null) {
            // Restore the ViewModelStore from NonConfigurationInstances
            mViewModelStore = nc.viewModelStore;
        }
        if (mViewModelStore == null) {
            mViewModelStore = new ViewModelStore();
        }
    }
}

ViewModelStore

最后来到了 ViewModelStore 。

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

ViewModelStore 作为一种缓存机制,通过键值对的形式来缓存 ViewModel 对象。

它的初始化在 ViewModelProvider 构造方法中:

public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
    mFactory = factory;
    mViewModelStore = store;
}

而 ViewModelProvider 的创建,是通过单一 ViewModelStoreOwner 参数的构造方法进来的,在这个方法中配置了 ViewModelStore 的来源:

public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
    this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
            ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
            : NewInstanceFactory.getInstance());
}

通过 owner.getViewModelStore() 来获取 ViewModelStore 对象,和 ComponentActivity / Fragment 中串起来了。

实现了 ViewModelStoreOwner 接口的组件内部会自动创建 ViewModelStore 。而 ViewModel 对象会缓存到 ViewModelStore ,也就是和这些组件产生了绑定关系。

那么也就是说,同一个 ViewModel 类型,在不同的 Activity 中的 ViewModel 实例可能是不同的。


原文始发于微信公众号(八千里路山与海):Android ViewModel 超详细分析

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/85062.html

(0)

相关推荐

发表回复

登录后才能评论
半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!