关于ViewModel的理解

相关类介绍

ViewModelStore

存储ViewModel的数据类 ,内部是一个HashMap
`public class ViewModelStore {

private final HashMap 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 keys() {
    return new HashSet<>(mMap.keySet());
}

/**
 *  Clears internal storage and notifies ViewModels that they are no longer used.
 * 在Activity销毁时会调用
 */
public final void clear() {
    for (ViewModel vm : mMap.values()) {
        vm.clear();
    }
    mMap.clear();
}

在Activity的构造方法中,会去拿到lifecycle, 通过观察lifecycle的生命周期,如果是on_Destroy
会调用viewmodelStrore的clear(),然后会去调用所有viewmodel的onCLear()

getLifecycle().addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    // Clear out the available context
                    mContextAwareHelper.clearAvailableContext();
                    // And clear the ViewModelStore
                    if (!isChangingConfigurations()) {  //后面分析
                        getViewModelStore().clear();
                    }
                }
            }
        });

###ViewModelProviders.Factory

ViewModelProviders的内部类,只有一个create方法,用于创建ViewModel

public interface Factory {
        /**
         * Creates a new instance of the given {@code Class}.
         * 

* * @param modelClass a {@code Class} whose instance is requested * @param The type parameter for the ViewModel. * @return a newly created ViewModel */ @NonNull T create(@NonNull Class modelClass); }

ViewModel创建

ViewModelProviders.of(this, new ViewModelFactory<>()).get(ViewModel.class)

原理

of(this, factary) 这句往下看:

public static ViewModelProvider of(@NonNull FragmentActivity activity,
            @Nullable Factory factory) {
        Application application = checkApplication(activity);
        if (factory == null) { //若factory为空  创建一个默认的factory 
            factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
        }
        
        //创建ViewModelProvider返回,将activity的viewModelStaore,以及factory当作变量存储
        return new ViewModelProvider(activity.getViewModelStore(), factory);
    }

get(ViewModel.class)

    public  T get(@NonNull Class modelClass) {
        String canonicalName = modelClass.getCanonicalName();
        if (canonicalName == null) {
            throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
        }
        //DEFAULT_KEY + ":" + canonicalName, modelClass为存储viewmodel的key
        return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
    }



     public  T get(@NonNull String key, @NonNull Class modelClass) {
        ViewModel viewModel = mViewModelStore.get(key); //从map中获取viewModel

        if (modelClass.isInstance(viewModel)) { //map中存在且为modelClass类型 则返回
            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); //通过factory创建viewmodel
        } 
        mViewModelStore.put(key, viewModel); //存储
        return (T) viewModel;
    }
   

以上就是ViewModel基本工作流程

ViewModel妙用

1、在Activity重建时可保存数据

在创建ViewModelProvider时,会通过Activty拿到ViewModelStore,通过ViewModelStore获取ViewModel

new ViewModelProvider(activity.getViewModelStore(), factory)

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

void ensureViewModelStore() {
        if (mViewModelStore == null) {
                //获取最近一次Activity重建时保存下来的数据
            NonConfigurationInstances nc =
                     (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                // Restore the ViewModelStore from NonConfigurationInstances
                mViewModelStore = nc.viewModelStore;
            }
            if (mViewModelStore == null) {
                mViewModelStore = new ViewModelStore();
            }
        }
    }
    

大家都知道Activty横竖屏切换时会触发onSaveInstanceState,而还原时会触发onRestoreInstanceState
,但是Android的Activity类还有一个方法名为onRetainNonConfigurationInstance和getLastNonConfigurationInstance这两个方法

在恢复窗口时,我们可以不使用 onRestoreInstanceState,而代替的是getLastNonConfigurationInstance

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

mLastNonConfigurationInstances在Activity attach阶段被赋值,分析Activity的生命周期具体调用时机,我们知道Activity是通过反射创建出来的,之后会执行attach方法,所以我猜测mLastNonConfigurationInstances是通过AMS传递过来,那么它是在哪里保存的呢?

在Activity configuration发生改变时,将伴随onDestroy被系统调用 ,onRetainNonConfigurationInstance也会被调用

 
  public final Object onRetainNonConfigurationInstance() {
        // Maintain backward compatibility.
        Object custom = onRetainCustomNonConfigurationInstance();

        ViewModelStore viewModelStore = mViewModelStore;
        if (viewModelStore == null) { 
         //获取最近一次Activity重建时保存下来的数据
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                viewModelStore = nc.viewModelStore;
            }
        }

        if (viewModelStore == null && custom == null) {
            return null;
        }
        

        NonConfigurationInstances nci = new NonConfigurationInstances();
        nci.custom = custom;
        nci.viewModelStore = viewModelStore;  //保存
        return nci;
    }

通过上述一系列操作保存Activity的ViewMdoel,也就实现了ViewModel的数据保存。

2、实现Activity与Fragment数据共享

Fragment依附在Activity之上,所以在创建Viewmdoel时可以传入当前的Actiivty,这时就会传回一个Activity已经创建好的ViewModel,这样就可以方便的访问到这个ViewModel上的数据,在Activity 修改数据后Fagment也可以拿到

public class MyFragment extends Fragment {
     public void onStart() {
        //这里拿到的ViewModel实例,其实是和Activity中创建的是一个实例
         UserModel userModel = ViewModelProviders.of(getActivity()).get(UserModel.class);
     }
 }

3、实现Fragemnt与Fragment之间数据共享

多个Fragment之间可通过Activity获取到同一个ViewModel,当在同一个Viewmodel中通过liveData更新数据
那么多个Fragment都可以收到。

你可能感兴趣的:(Android学习,java,c#,android)