Jetpack-ViewModel源码分析

ViewModel简介

1. Activity或Fragment有自己的生命周期被Framework所管理,Framework可能会根据用户的一些操作以及设备的状态对Actvity或Fragment进行销毁和重建。伴随着Activity或Fragment的销毁和重建,它们当中的数据也会随着一起销毁和重建。对于一些简单的数据,Activity可以使用onSaveInstanceState()方法,并从onCreate的bundle中重新获取,但这一方法仅仅适合一些简单的UI状态,对于列表型这种庞大的数据类型并不适合。
2. Activity或Fragment经常会做一些异步的耗时操作,需要管理这些异步操作得到的数据,并在destroyed的时候清理它们,从而避免内存溢出这类问题的发生。管理数据的成本较大,另外configurationChanged发生时,部分资源和数据需要重新请求,降低了性能。
3. Activity或Fragment本身需要处理很多用户的输入事件并和操作系统相关操作们,如果还维护管理业务数据和资源,会导致Activity和Fragment过于庞大。

特点

以关联生命周期的方式来存储和管理UI相关的数据,即使configuration发生改变(比如旋转屏幕,系统语言字体变化),数据仍然可以存在不会销毁。
Activity和Fragment之间,多个Fragment之间共享数据,轻松解决Activity和Fragment之间数据通信提高复杂性问题。

职责

Jetpack-ViewModel源码分析_第1张图片
ViewModel类图

ViewModel
ViewModel 对象为特定的界面组件提供数据,并包含数据处理业务逻辑,以与模型进行通信。
ViewModel被更换或者清除时,通过onCleard释放持有资源。

ViewModelStore
负责缓存ViewModel,通过clear释放ViewModel持有资源。

ViewModelStoreOwner
负责持有ViewModelStore,Support Library 28中Fragemnt,Activity和HoldFragment是ViewModelStoreOwner的具体实现类,他们内部持有ViewModelStore。

ViewModelStores
负责通过Activity或者Fragment获取ViewModelStore。
1. 如果Activity或者Fragment已实现ViewModelStoreOwner接口,直接返回内部ViewModelStore;
2. 如果Activity或者Fragment未实现ViewModelStoreOwner接口,通过HoldFragment机制获得ViewModelStore;

ViewModelProvider
负责获取ViewModel实例,构造ViewModelProvider需要ViewModelStore和Factory。

1. 根据ViewModel Class名称,从ViewModelStore缓存中获取ViewModel实例;
2. 步骤1获取成功,直接返回实例;
3. 步骤1获取失败,通过Factory反射构造ViewModel,内置Factory有NewInstanceFactory,AndroidViewModelFactory。
4. 使用ViewModelStore缓存步骤3创建的ViewModel实例后,返回ViewModel实例。

ViewModelProviders
负责为Activity和Fragment创建ViewModelProvider。

源码解析

使用

在Activity或者Fragment中获得ViewModel实例。

class MainFragment : Fragment() {
    companion object {
        fun newInstance() = MainFragment()
    }
    private lateinit var viewModel: MainViewModel
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View {
        return inflater.inflate(R.layout.main_fragment, container, false)
    }
    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
    }
}

上面的样例代码中使用最简单的方式构造ViewModel,通过ViewModelProvider内部自动构造ViewModel,如果需要把Repository等其他对象内置到ViewModel中,可以自定义Factory去实现。这篇文章主要是分析ViewModel内部实现机制,不对ViewModel的构造太多介绍,可以参见android-architecture-components-BasicSample。

关键源码分析

相关源码中比较关键是的ViewModelStores,HoldFragment。

ViewModelStores

public class ViewModelStores {
    private ViewModelStores() {
    }
    public static ViewModelStore of(@NonNull FragmentActivity activity) {
        if (activity instanceof ViewModelStoreOwner) {
            return ((ViewModelStoreOwner) activity).getViewModelStore();
        }
        return holderFragmentFor(activity).getViewModelStore();
    }
    public static ViewModelStore of(@NonNull Fragment fragment) {
        if (fragment instanceof ViewModelStoreOwner) {
            return ((ViewModelStoreOwner) fragment).getViewModelStore();
        }
        return holderFragmentFor(fragment).getViewModelStore();
    }
}
  1. 如果Activity或者Fragment实现ViewModelOwner,直接返回内部的ViewModelStore;
  2. 否则,通过HoldFragment获得ViewModelStore。

注意:无论哪种方式,都实现了对应Activity或者Fragment只存在一个ViewModelStore,且根据Activity和Fragment生命周期销毁(configurationChanged除外)。

HoldFragment

public class HolderFragment extends Fragment implements ViewModelStoreOwner {
    //仅存在一个HolderFragmentManager实例
    private static final HolderFragmentManager sHolderFragmentManager = new HolderFragmentManager();
    private ViewModelStore mViewModelStore = new ViewModelStore();
    public HolderFragment() {
//保留Fragment
        setRetainInstance(true);
    }
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        sHolderFragmentManager.holderFragmentCreated(this);
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        mViewModelStore.clear();
    }
    @Override
    public ViewModelStore getViewModelStore() {
        return mViewModelStore;
    }
    public static HolderFragment holderFragmentFor(FragmentActivity activity) {
        return sHolderFragmentManager.holderFragmentFor(activity);
    }
    
static class HolderFragmentManager {
        private Map mNotCommittedActivityHolders = new HashMap<>(); 
private Map mNotCommittedFragmentHolders = new HashMap<>();
...
}

1. HoldFragment实现ViewModelStoreOwner接口;
2.setRetainInstance,configurationChanged后,短暂保留Fragment,从而保留ViewModelStore[参考];
3. onDestory时,ViewModelStore clear;
4. sHolderFragmentManager仅存在一个实例;
5. NotCommitted变量和holderFragmentCreated规避为一个Activity或者Fragment创建多个HoldFragment。

Support Library

support v4 28.0.0 中FragmentActivity和Fragment已实现ViewModelStoreOwner接口,不再需要HoldFragment机制支持ViewModel特性。

Fragment

通过在OnDestroy方法对configuration的判断,保留下ViewModelStore。

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

FragmentActivity

了解下NonConfigurationInstances,此处不再赘述。

public class FragmentActivity extends SupportActivity implements ViewModelStoreOwner {
    private ViewModelStore mViewModelStore;
    public ViewModelStore getViewModelStore() {
        if (this.getApplication() == null) {
            throw new IllegalStateException("Your activity is not yet attached to the Application instance. You can't request ViewModel before onCreate call.");
        } else {
            if (this.mViewModelStore == null) {
                FragmentActivity.NonConfigurationInstances nc = (FragmentActivity.NonConfigurationInstances)this.getLastNonConfigurationInstance();
                if (nc != null) {
                    this.mViewModelStore = nc.viewModelStore;
                }

                if (this.mViewModelStore == null) {
                    this.mViewModelStore = new ViewModelStore();
                }
            }
            return this.mViewModelStore;
        }
    }
   protected void onCreate(@Nullable Bundle savedInstanceState) {
        this.mFragments.attachHost((Fragment)null);
        super.onCreate(savedInstanceState);
        FragmentActivity.NonConfigurationInstances nc = (FragmentActivity.NonConfigurationInstances)this.getLastNonConfigurationInstance();
        if (nc != null && nc.viewModelStore != null && this.mViewModelStore == null) {
            this.mViewModelStore = nc.viewModelStore;
        }
   }
    protected void onDestroy() {
        super.onDestroy();
        if (this.mViewModelStore != null && !this.isChangingConfigurations()) {
            this.mViewModelStore.clear();
        }
        this.mFragments.dispatchDestroy();
    }
}

总结

Jetpack中ViewModel的设计和实现并不是很复杂,ViewModel是Google官方推荐MVVM模式实现的重要组成部分,ViewModel与Lifecycle和LiveData等Jetpack组件组合使用会更加发挥其作用,待后续深入分析其他Jetpack组件源码实现。

你可能感兴趣的:(Jetpack-ViewModel源码分析)