连云港网站建设多少钱,贵州省建设局八大员报名网站,大连旅游网站建设,在哪个网站可以学做衣服The ViewModel class is a business logic or screen level state holder. 上面是官方给的定义#xff0c;ViewModel 类是业务逻辑或屏幕级状态持有者。
一、业务逻辑持有者
在此之前#xff0c;无论是MVC模式#xff0c;还是MVP模式#xff0c;在视图层#xff0c;都会… The ViewModel class is a business logic or screen level state holder. 上面是官方给的定义ViewModel 类是业务逻辑或屏幕级状态持有者。
一、业务逻辑持有者
在此之前无论是MVC模式还是MVP模式在视图层都会产生对业务逻辑层的依赖从而导致出现内存泄漏的情况。那ViewModel又是如何处理业务逻辑层和视图层的依赖从而避免了常见的内存泄漏的问题的呢
依赖Lifecycle对宿主生命周期的感知处理对Viewmodel的依赖
1.1、应用
NormalViewModel
package com.anniljing.viewmodelcorestudy;import android.app.Application;import java.util.ArrayList;
import java.util.List;import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;public class NormalViewModel extends AndroidViewModel {public NormalViewModel(NonNull Application application) {super(application);}public ListInteger getdatas() {ListInteger data new ArrayList();for (int i 0; i 10; i) {data.add(i);}return data;}
}
NormalActivity
package com.anniljing.viewmodelcorestudy;import android.os.Bundle;import com.anniljing.viewmodelcorestudy.databinding.ActivityNormalBinding;import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;public class NormalActivity extends AppCompatActivity {private ActivityNormalBinding mBinding;private NormalViewModel mViewModel;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mBinding ActivityNormalBinding.inflate(getLayoutInflater());setContentView(mBinding.getRoot());mViewModel new ViewModelProvider(this).get(NormalViewModel.class);}
}ComponentActivity源码 getLifecycle().addObserver(new LifecycleEventObserver() {Overridepublic void onStateChanged(NonNull LifecycleOwner source,NonNull Lifecycle.Event event) {if (event Lifecycle.Event.ON_DESTROY) {// Clear out the available contextmContextAwareHelper.clearAvailableContext();// And clear the ViewModelStoreif (!isChangingConfigurations()) {getViewModelStore().clear();}}}});此处在Activity中Lifecycle的ON_DESTROY事件中清除了ViewModel。
1.2、源码解析 1.2.1 创建ViewModelStore
public ComponentActivity() {Lifecycle lifecycle getLifecycle();//noinspection ConstantConditionsif (lifecycle null) {throw new IllegalStateException(getLifecycle() returned null in ComponentActivitys constructor. Please make sure you are lazily constructing your Lifecycle in the first call to getLifecycle() rather than relying on field initialization.);}getLifecycle().addObserver(new LifecycleEventObserver() {Overridepublic void onStateChanged(NonNull LifecycleOwner source,NonNull Lifecycle.Event event) {if (event Lifecycle.Event.ON_DESTROY) {// Clear out the available contextmContextAwareHelper.clearAvailableContext();// And clear the ViewModelStoreif (!isChangingConfigurations()) {getViewModelStore().clear();}}}});getLifecycle().addObserver(new LifecycleEventObserver() {Overridepublic void onStateChanged(NonNull LifecycleOwner source,NonNull Lifecycle.Event event) {ensureViewModelStore();getLifecycle().removeObserver(this);}});}在ComponentActivity的构造方法中注册了多个Lifecycle的观察者其中有两个涉及ViewModelStore的一个是收到宿主的生命周期事件后就创建了ViewModelStore,随后就移除了该观察者另一个则是监听到宿主的ON_DESTROY事件后清空ViewModelStore的ViewModel
1.2.2、创建Factory
1.2.2.1、创建ViewModel的时候第一步我们创建了ViewModelProvider调用了其中一个构造方法 public constructor(owner: ViewModelStoreOwner) : this(owner.viewModelStore, defaultFactory(owner), defaultCreationExtras(owner))1.2.2.2、ViewModelProvider的构造方法中调用了默认的Factory
public companion object {internal fun defaultFactory(owner: ViewModelStoreOwner): Factory if (owner is HasDefaultViewModelProviderFactory)owner.defaultViewModelProviderFactory else instanceinternal const val DEFAULT_KEY androidx.lifecycle.ViewModelProvider.DefaultKey}1.2.2.3、由于ComponentActivity实现了HasDefaultViewModelProviderFactory接口所以Factory的实际对象是SavedStateViewModelFactory NonNullOverridepublic ViewModelProvider.Factory getDefaultViewModelProviderFactory() {if (mDefaultFactory null) {mDefaultFactory new SavedStateViewModelFactory(getApplication(),this,getIntent() ! null ? getIntent().getExtras() : null);}return mDefaultFactory;}1.2.3、创建ViewModel
public open operator fun T : ViewModel get(key: String, modelClass: ClassT): T {val viewModel store[key]if (modelClass.isInstance(viewModel)) {(factory as? OnRequeryFactory)?.onRequery(viewModel)return viewModel as T} else {Suppress(ControlFlowWithEmptyBody)if (viewModel ! null) {// TODO: log a warning.}}val extras MutableCreationExtras(defaultCreationExtras)extras[VIEW_MODEL_KEY] key// AGP has some desugaring issues associated with compileOnly dependencies so we need to// fall back to the other create method to keep from crashing.return try {factory.create(modelClass, extras)} catch (e: AbstractMethodError) {factory.create(modelClass)}.also { store.put(key, it) }}应用层通过ViewModelProvider的get方法创建ViewModel,并且保存到ViewModelStore中。
二、屏幕状态的持有者
该功能主要处理当设备配置发生变化时界面会重新绘制导致数据丢失的问题。 屏幕发生旋转的时候会调用onDestroy方法界面会重新绘制。
2.1、ViewModel之前
2.1.1、manifest中配置 在activity里面的configChanges属性里面配置orientation|screenSize则屏幕旋转的时候界面就不会重新绘制。
2.1.2、onSaveInstanceState和onRestoreInstanceState
如果manifest里面没有配置configChanges则屏幕旋转的时候在onDestroy之前会调用onSaveInstanceState在恢复界面的时候会调用onRestoreInstanceState这样我们就可以在以上两个方法中做保存和恢复数据的逻辑。
package com.anniljing.viewmodelcorestudy;import android.os.Bundle;
import android.util.Log;import com.anniljing.viewmodelcorestudy.databinding.ActivitySaveStateBinding;import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;public class SaveStateActivity extends AppCompatActivity {private static final String TAG SaveStateActivity;private ActivitySaveStateBinding mBinding;private NormalState mNormalState;private static final String KEYNormalState;private String saveString;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Log.e(TAG, onCreate);if (savedInstanceState !null){saveStringsavedInstanceState.getString(KEY,);}mBinding ActivitySaveStateBinding.inflate(getLayoutInflater());setContentView(mBinding.getRoot());mNormalState new NormalState();mNormalState.setString(saveString);Log.e(TAG, mNormalState.getString());mBinding.tvState.setOnClickListener((view) - {mNormalState.setString(NormalState);Log.e(TAG,Click after: mNormalState.getString());});}Overrideprotected void onSaveInstanceState(NonNull Bundle outState) {super.onSaveInstanceState(outState);Log.e(TAG, onSaveInstanceState);outState.putString(KEY,NormalState);}Overrideprotected void onRestoreInstanceState(NonNull Bundle savedInstanceState) {super.onRestoreInstanceState(savedInstanceState);Log.e(TAG, onRestoreInstanceState);}Overrideprotected void onDestroy() {super.onDestroy();Log.e(TAG, onDestroy);}
}保存数据 重新绘制的时候取出数据 在onSaveInstanceState里面增加保存逻辑在onCreate方法里面就可以恢复以前的数据了。
2.2、 使用ViewModel
ViewModelSaveState
package com.anniljing.viewmodelcorestudy;import android.app.Application;import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;public class ViewModelSaveState extends AndroidViewModel {private String mString;public ViewModelSaveState(NonNull Application application) {super(application);}public String getString() {return mString;}public void setString(String string) {mString string;}
}
package com.anniljing.viewmodelcorestudy;import android.os.Bundle;
import android.util.Log;import com.anniljing.viewmodelcorestudy.databinding.ActivitySaveStateBinding;import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;public class SaveStateActivity extends AppCompatActivity {private static final String TAG SaveStateActivity;private ActivitySaveStateBinding mBinding;private ViewModelSaveState mViewModelSaveState;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Log.e(TAG, onCreate);mBinding ActivitySaveStateBinding.inflate(getLayoutInflater());setContentView(mBinding.getRoot());mViewModelSaveState new ViewModelProvider(this).get(ViewModelSaveState.class);Log.e(TAG,Before click:mViewModelSaveState.getString());mBinding.tvState.setOnClickListener((view) - {mViewModelSaveState.setString(ViewModelState);Log.e(TAG, Click after: mViewModelSaveState.getString());});}Overrideprotected void onDestroy() {super.onDestroy();Log.e(TAG,onDestroy);}
}可以看到引入ViewModel以后不需要在onSaveInstanceState方法中增加额外的保存逻辑重绘后就可以恢复以前的数据。
无论是ViewModel,还是重写onSaveInstanceState方法当内存有限导致界面退出重绘时就无法恢复以前的数据了。 我们可以通过以下操作来模拟内存不足时导致应用杀死的效果 1、启用开发者模式 2、打开“不保留活动” 3、打开应用后按home键退出应用 4、重新打开应用。
2.3、使用SavedStateHandle
ViewModelWithHandleSaveState
package com.anniljing.viewmodelcorestudy;import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.SavedStateHandle;
import androidx.lifecycle.ViewModel;public class ViewModelWithHandleSaveState extends ViewModel {private static final String KEY ViewModelWithHandleSaveState;private SavedStateHandle mStateHandle;public ViewModelWithHandleSaveState(SavedStateHandle stateHandle) {mStateHandle stateHandle;}public MutableLiveDataString getLiveData() {return mStateHandle.getLiveData(KEY);}
}
1、构造方法里面添加SavedStateHandle参数。 2、获取的时候通过mStateHandle。 SaveStateActivity
package com.anniljing.viewmodelcorestudy;import android.os.Bundle;
import android.util.Log;import com.anniljing.viewmodelcorestudy.databinding.ActivitySaveStateBinding;import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;public class SaveStateActivity extends AppCompatActivity {private static final String TAG SaveStateActivity;private ActivitySaveStateBinding mBinding;private ViewModelWithHandleSaveState mWithHandleSaveState;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Log.e(TAG, onCreate);mBinding ActivitySaveStateBinding.inflate(getLayoutInflater());setContentView(mBinding.getRoot());mWithHandleSaveState new ViewModelProvider(this).get(ViewModelWithHandleSaveState.class);Log.e(TAG, Before click: mWithHandleSaveState.getLiveData().getValue());mWithHandleSaveState.getLiveData().observe(this, s - {Log.e(TAG, After click: mWithHandleSaveState.getLiveData().getValue());});mBinding.tvState.setOnClickListener((view) - mWithHandleSaveState.getLiveData().postValue(ViewModelWithHandleSaveState));}Overrideprotected void onDestroy() {super.onDestroy();Log.e(TAG, onDestroy);}
}