Jetpack-ViewModel浅析

207 阅读2分钟

ViewModel 是 Jetpack 中的一个组件,它以注重生命周期的方式管理界面的相关数据。 ViewModel的优势是数据持久化,即使手机在横竖屏切换时数据依然存在。

ViewModel的使用

val mViewModel = ViewModelProvider(this).get(UserViewModel::class.java)

ViewModel的创建过程

当执行ViewModelProvider(this).get(UserViewModel::class.java)代码时,会从ViewModelStore中通过类名+ViewModel实例作为key取出ViewModel,如果没有这会创建一个ViewModel出来,然后再存到ViewModelStore中。

public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
    // 会从ViewModelStore中的HashMap中取出ViewModel
    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;
}

接着再看ViewModelProvider的构造方法


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

因为ComponentActivity实现了HasDefaultViewModelProviderFactory接口,所以会执行ComponentActivity中的getDefaultViewModelProviderFactory()方法

public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
    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 (mDefaultFactory == null) {
        mDefaultFactory = new SavedStateViewModelFactory(
                getApplication(),
                this,
                getIntent() != null ? getIntent().getExtras() : null);
    }
    return mDefaultFactory;
}

接着再看SavedStateViewModelFactory中的create方法

// 通过反射去创建ViewModel实例
public <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) {
    boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
    Constructor<T> constructor;
    if (isAndroidViewModel) {
        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) {
            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);
    }
}

数据的存储和恢复

在ComponentActivity类中通过Bundle进行数据的存储和恢复,Bundle作为数据存储,已经和当前Activity实例没有任何关系了。

protected void onCreate(@Nullable Bundle savedInstanceState) {
    // Restore the Saved State first so that it is available to
    // OnContextAvailableListener instances
    mSavedStateRegistryController.performRestore(savedInstanceState);
    //........
}
protected void onSaveInstanceState(@NonNull Bundle outState) {
    //..........
    mSavedStateRegistryController.performSave(outState);
}

生命周期管理

在ComponentActivity的构造方法中有这样一段代码,通过Lifecycle对生命周期进行监听。

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

当isChangingConfigurations()方法返回false时说明屏幕状态没有发生改变,此时会执行ViewModelStore的clear()方法,在clear方法中会循环遍历HashMap中保存的ViewModel对象,调用ViewModel对象的onCleared()方法,在这个方法中执行具体的对象销毁操作。

public final void clear() {
    for (ViewModel vm : mMap.values()) {
        vm.clear();
    }
    mMap.clear();
}