其他
看完这篇文章,Jetpack的ViewModel闭着眼睛用
https://www.jianshu.com/u/257511d0c878
https://github.com/TanJiaJunBeyond/ViewModelDemo
enabled = true
}
import androidx.databinding.Observable
import androidx.databinding.PropertyChangeRegistry
import androidx.lifecycle.ViewModel
/**
* Created by TanJiaJun on 2019-11-24.
*/
open class ObservableViewModel : ViewModel(), Observable {
private val callbacks = PropertyChangeRegistry()
override fun addOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback?) =
callbacks.add(callback)
override fun removeOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback?) =
callbacks.remove(callback)
fun notifyChange() =
callbacks.notifyCallbacks(this, 0, null)
fun notifyPropertyChanged(fieldId: Int) =
callbacks.notifyCallbacks(this, fieldId, null)
}
第一个例子:ViewModel不会因为配置更改而被销毁
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main).also {
it.viewModel = ViewModelProviders.of(this)[MainViewModel::class.java].apply {
name = "谭嘉俊"
age = 25
gender = "男"
}
it.handlers = this
}
}
第二个例子是:Fragment使用Activity共享的ViewModel处理数据
import androidx.databinding.Bindable
import androidx.databinding.library.baseAdapters.BR
/**
* Created by TanJiaJun on 2019-11-24.
*/
class NameViewModel : ObservableViewModel() {
@get:Bindable
var name = ""
set(value) {
field = value
notifyPropertyChanged(BR.name)
}
}
private var viewModel: NameViewModel? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// retainInstance方法下面会解析
retainInstance = true
viewModel = activity?.let {
ViewModelProviders.of(it)[NameViewModel::class.java].apply {
name = "谭嘉俊"
}
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? =
DataBindingUtil.inflate<FragmentFirstNameBinding>(
inflater,
R.layout.fragment_first_name,
container,
false
)
.also {
// 使用NameActivity共享的NameViewModel
it.viewModel = viewModel
it.handlers = this
}
.root
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? =
DataBindingUtil.inflate<FragmentSecondNameBinding>(
inflater,
R.layout.fragment_second_name,
container,
false
)
.also { it.handlers = this }
.root
// 点击按钮后会改变NameViewModel中name的属性值
override fun onChangeNameToAppleClick(view: View) {
activity?.let { ViewModelProviders.of(it)[NameViewModel::class.java].name = "苹果" }
}
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull Fragment fragment) {
return of(fragment, null);
}
// 创建一个ViewModelProvider,在Activity处于活动状态时保留ViewModel
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity) {
return of(activity, null);
}
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull Fragment fragment, @Nullable Factory factory) {
// 检查Fragment是否附加在Application
Application application = checkApplication(checkActivity(fragment));
// 在上面的方法中factory是传null
if (factory == null) {
// 创建一个单例的AndroidViewModelFactory
factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}
// 创建ViewModelProvider,这里会拿到Fragment的ViewModelStore,下面会分析
return new ViewModelProvider(fragment.getViewModelStore(), factory);
}
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
// 检查Activity是否附加在Application
Application application = checkApplication(activity);
// 在上面的方法中factory是传null
if (factory == null) {
// 创建一个单例的AndroidViewModelFactory
factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}
// 创建ViewModelProvider,这里会拿到Activity的ViewModelStore,下面会分析
return new ViewModelProvider(activity.getViewModelStore(), factory);
}
@Override
public ViewModelStore getViewModelStore() {
// 检查Activity是否附加在Application
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 (mViewModelStore == null) {
// 通过getLastNonConfigurationInstance()方法得到NonConfigurationInstances,下面会分析
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// 从NonConfigurationInstances恢复ViewModelStore
mViewModelStore = nc.viewModelStore;
}
// 如果是空的话创建ViewModelStore对象
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
// NonConfigurationInstances是一个final的静态类,里面有两个变量:custom和viewModelStore
static final class NonConfigurationInstances {
Object custom;
ViewModelStore viewModelStore;
}
@Override
@Nullable
public final Object onRetainNonConfigurationInstance() {
// onRetainCustomNonConfigurationInstance()方法已弃用
Object custom = onRetainCustomNonConfigurationInstance();
ViewModelStore viewModelStore = mViewModelStore;
if (viewModelStore == null) {
// 如果viewModelStore是null的话,证明没人调用getViewModelStore(),所以看看我们最后一个NonConfigurationInstance是否存在ViewModelStore
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// 如果有的话,就从NonConfigurationInstances取出ViewModelStore
viewModelStore = nc.viewModelStore;
}
}
if (viewModelStore == null && custom == null) {
// 如果ViewModelStore还是null而且custom也是null的话,证明没有NonConfigurationInstances
return null;
}
// 如果有ViewModelStore或者有custom的话,就创建NonConfigurationInstances对象,并且对其进行赋值
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = viewModelStore;
return nci;
}
// 创建一个key为String,value为ViewModel的HashMap对象
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);
}
Set<String> keys() {
return new HashSet<>(mMap.keySet());
}
// 清除内部存储并且通知存储在这个HashMap中的所有的ViewModel不再被使用
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
mViewModelStore = store;
}
private static final String DEFAULT_KEY =
"androidx.lifecycle.ViewModelProvider.DefaultKey";
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
// 得到ViewModel的Class对象的Java语言规范定义的底层类的规范名称
String canonicalName = modelClass.getCanonicalName();
if (canonicalName == null) {
throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
}
// 调用下面的get方法,传入“DEFAULT_KEY:modelClass的规范名称”字符串和ViewModel的Class对象
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
@SuppressWarnings("unchecked")
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
// 通过key从ViewModelStore中的HashMap中得到ViewModel
ViewModel viewModel = mViewModelStore.get(key);
// 判断从ViewModelStore中得到的ViewModel是否是Class对象的一个实例,也就是说判断ViewModelStore中是否存在我们想要的ViewModel
if (modelClass.isInstance(viewModel)) {
// 如果有的话就返回对应的ViewModel
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
// 如果没有的话就创建ViewModel
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
} else {
// 根据上面的代码可知,mFactory是Factory的实现类NewInstanceFactory的子类AndroidViewModelFactory,所以我们调用的是这段逻辑
viewModel = (mFactory).create(modelClass);
}
// 将创建好的ViewModel存放到ViewModelStore
mViewModelStore.put(key, viewModel);
// 返回ViewModel
return (T) viewModel;
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
// 判断AndroidViewModel所表示的类或接口是否与modelClass所表示的类或接口相同,或者是否为其超类或超接口
if (AndroidViewModel.class.isAssignableFrom(modelClass)) {
//noinspection TryWithIdenticalCatches
try {
// 创建ViewModel对象
return modelClass.getConstructor(Application.class).newInstance(mApplication);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (InstantiationException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
} catch (InvocationTargetException e) {
throw new RuntimeException("Cannot create an instance of " + modelClass, e);
}
}
// 根据我们的示例代码,我们传入的modelClass不是AndroidViewModel,而且也不是为其超类或者超接口,所以会执行以下逻辑
return super.create(modelClass);
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
//noinspection TryWithIdenticalCatches
try {
// 创建由modelClass类对象表示的类的新实例
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);
}
}
@NonNull
@Override
public ViewModelStore getViewModelStore() {
// 判断Fragment是否已经与Activity分离
if (mFragmentManager == null) {
throw new IllegalStateException("Can't access ViewModels from detached fragment");
}
return mFragmentManager.getViewModelStore(this);
}
@NonNull
ViewModelStore getViewModelStore(@NonNull Fragment f) {
return mNonConfig.getViewModelStore(f);
}
@NonNull
ViewModelStore getViewModelStore(@NonNull Fragment f) {
ViewModelStore viewModelStore = mViewModelStores.get(f.mWho);
if (viewModelStore == null) {
viewModelStore = new ViewModelStore();
mViewModelStores.put(f.mWho, viewModelStore);
}
return viewModelStore;
}
// 省略部分代码
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
// 判断是否接收到Activity的destroy状态
if (event == Lifecycle.Event.ON_DESTROY) {
// 如果接收到,判断是否因为配置更改导致的destroy
if (!isChangingConfigurations()) {
// 如果不是,调用ViewModelStore的clear方法
getViewModelStore().clear();
}
}
}
});
// 省略部分代码
}
void clearNonConfigState(@NonNull Fragment f) {
if (FragmentManagerImpl.DEBUG) {
Log.d(FragmentManagerImpl.TAG, "Clearing non-config state for " + f);
}
// 清除并且删除Fragment的子配置状态
FragmentManagerViewModel childNonConfig = mChildNonConfigs.get(f.mWho);
if (childNonConfig != null) {
childNonConfig.onCleared();
mChildNonConfigs.remove(f.mWho);
}
// 清除并且删除Fragment的ViewModelStore
ViewModelStore viewModelStore = mViewModelStores.get(f.mWho);
if (viewModelStore != null) {
viewModelStore.clear();
mViewModelStores.remove(f.mWho);
}
}
@SuppressWarnings("ReferenceEquality")
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
// 省略部分代码
if (f.mState <= newState) {
// 省略部分代码
} else if (f.mState > newState) {
switch (f.mState) {
// 省略部分代码
case Fragment.CREATED:
if (newState < Fragment.CREATED) {
// 省略部分代码
if (f.getAnimatingAway() != null || f.getAnimator() != null) {
// 省略部分代码
} else {
if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
boolean beingRemoved = f.mRemoving && !f.isInBackStack();
// 判断Fragment是否正在remove,同时还没放入后退栈,或者判断是否FragmentManagerViewModel是否应该销毁
if (beingRemoved || mNonConfig.shouldDestroy(f)) {
boolean shouldClear;
// 判断mHost是否是ViewModelStoreOwner的实例
if (mHost instanceof ViewModelStoreOwner) {
// 如果是,shouldClear的值就是FragmentManagerViewModel是否已经清除
shouldClear = mNonConfig.isCleared();
} else if (mHost.getContext() instanceof Activity) {
Activity activity = (Activity) mHost.getContext();
shouldClear = !activity.isChangingConfigurations();
} else {
shouldClear = true;
}
// 根据beingRemoved或者shouldClear的值来判断是否需要清除ViewModel
if (beingRemoved || shouldClear) {
// 如果是,调用clearNonConfigState方法
mNonConfig.clearNonConfigState(f);
}
// 执行Fragment的onDestroy()方法
f.performDestroy();
dispatchOnFragmentDestroyed(f, false);
} else {
f.mState = Fragment.INITIALIZING;
}
// 省略部分代码
}
}
}
}
// 省略部分代码
}
应用的进程在后台的时候由于内存限制而被终止。 配置更改。
ViewModel可以架构设计更加良好,UI代码和数据分离,使代码更加遵循单一职责原则、更加模块化、更易于测试。 ViewModel能储存更大、更复杂的数据,而且数据类型也没有限制,甚至可以储存Activity实例。
density:显示密度发生变更,例如:用户可能已指定不同的显示比例,或者有不同的显示现处于活跃状态。请注意:此项为 API 级别 24 中的新增配置。 fontScale:字体缩放系数发生变更,例如:用户已选择新的全局字号。 keyboard:键盘类型发生变更,例如:用户插入外置键盘。 keyboardHidden:键盘无障碍功能发生变更,例如:用户显示硬键盘。 layoutDirection:布局方向发生变更,例如:自从左至右 (LTR) 更改为从右至左 (RTL)。**请注意:此项为 API 级别 17 中的新增配置。 locale:语言区域发生变更,例如:用户已为文本选择新的显示语言。 mcc:IMSI 移动设备国家/地区代码 (MCC) 发生变更,例如:检测到 SIM 并更新 MCC。 mnc:IMSI 移动设备网络代码 (MNC) 发生变更,例如:检测到 SIM 并更新 MNC。 navigation:导航类型(轨迹球/方向键)发生变更。(这种情况通常不会发生。) orientation:屏幕方向发生变更,例如:用户旋转设备。请注意:如果应用面向 Android 3.2(API 级别 13)或更高版本的系统,则还应声明screenSize配置,因为当设备在横向与纵向之间切换时,该配置也会发生变更。 screenLayout:屏幕布局发生变更,例如:不同的显示现可能处于活跃状态。 screenSize:当前可用屏幕尺寸发生变更。该值表示当前可用尺寸相对于当前纵横比的变更,当用户在横向与纵向之间切换时,它便会发生变更。请注意:此项为 API 级别 13 中的新增配置。 smallestScreenSize:物理屏幕尺寸发生变更。该值表示与方向无关的尺寸变更,因此它只有在实际物理屏幕尺寸发生变更(如切换到外部显示器)时才会变化。对此配置所作变更对应smallestWidth配置的变化。请注意:此项为 API 级别 13 中的新增配置。 touchscreen:触摸屏发生变更。(这种情况通常不会发生。) uiMode:界面模式发生变更,例如:用户已将设备置于桌面或车载基座,或者夜间模式发生变更。如需了解有关不同界面模式的更多信息,请参阅UiModeManager。请注意:此项为 API 级别 8 中的新增配置。