ViewModel是什么?
ViewModel 类是一种业务逻辑或屏幕级状态容器。它用于将状态公开给界面,以及封装相关的业务逻辑。 它的主要优点是,它可以缓存状态,并可在配置更改后持久保留相应状态。这意味着在 activity 之间导航时或进行配置更改后(例如旋转屏幕时),界面将无需重新提取数据。
ViewModel解决什么问题?
如下是MVP架构中播放暂停按钮的实现
class MainActivity : AppCompatActivity(), PlayPresenter.PlayStateChangeListener {
val TAG = "MainActivity"
private lateinit var playBtn: Button
private val playPresenter: PlayPresenter by lazy { PlayPresenter() }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
playPresenter.setOnPlayStateChangeListener(this)
playBtn = findViewById<Button>(R.id.playBtn)
playBtn.setOnClickListener {
playPresenter.playOrStop()
}
}
override fun onPlayStateChange(playState: PlayPresenter.PlayState) {
when (playState) {
PlayPresenter.PlayState.PLAYING -> {
playBtn.text = "PLAYING"
}
PlayPresenter.PlayState.STOP -> {
playBtn.text = "STOP"
}
}
}
}
class PlayPresenter {
private lateinit var listener: PlayStateChangeListener
private var currentState = PlayState.STOP
enum class PlayState {
PLAYING, STOP
}
fun playOrStop() {
when (currentState) {
PlayState.STOP -> currentState = PlayState.PLAYING
PlayState.PLAYING -> currentState = PlayState.STOP
}
listener.onPlayStateChange(currentState)
}
interface PlayStateChangeListener {
fun onPlayStateChange(playState: PlayState)
}
fun setOnPlayStateChangeListener(listener: PlayStateChangeListener) {
this.listener = listener
}
}
利用LiveData可以省略监听和回调过程,而用ViewModel代替PlayPresenter,ViewModel主要优势实际上有两个方面:
- 它允许您持久保留界面状态
- 它可以提供对业务逻辑的访问权限
ViewModel实现
本文使用的版本如下,版本不一样需要更新AS及Gradle

class MainActivity : AppCompatActivity() {
val TAG = "MainActivity"
private lateinit var playBtn: Button
private val playModel by lazy { ViewModelProvider(this).get(PlayModel::class.java) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
playModel.currentState.observe(this, Observer<Any?> {
when (it) {
PlayModel.PlayState.PLAYING -> {
playBtn.text = "PLAYING"
}
PlayModel.PlayState.STOP -> {
playBtn.text = "STOP"
}
}
})
playBtn = findViewById<Button>(R.id.playBtn)
playBtn.setOnClickListener { playModel.playOrStop() }
}
}
class PlayModel : ViewModel() {
val currentState = MutableLiveData<PlayState>(PlayState.STOP)
enum class PlayState {
PLAYING, STOP
}
fun playOrStop() {
when (currentState.value) {
PlayState.STOP -> currentState.postValue(PlayState.PLAYING)
PlayState.PLAYING -> currentState.postValue(PlayState.STOP)
else -> {}
}
}
}
如果导入
implementation 'androidx.activity:activity-ktx:1.8.0'
则可以通过by viewModels()简化初始化,其是ComponentActivity的扩展函数,本质是通过ComponentActivity提供的默认工厂/参数创建ViewModel
private val playModel: PlayModel by viewModels()
ViewModel源码解析
ViewModelStoreOwner
实现类含有ViewModelStore
interface ViewModelStoreOwner {
val viewModelStore: ViewModelStore
}
ViewModelStore
通过包含全限定类名的String从map中存取对应的ViewModel
open class ViewModelStore {
private val map = mutableMapOf<String, ViewModel>()
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
fun put(key: String, viewModel: ViewModel) {
val oldViewModel = map.put(key, viewModel)
oldViewModel?.onCleared()
}
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
operator fun get(key: String): ViewModel? {
return map[key]
}
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
fun keys(): Set<String> {
return HashSet(map.keys)
}
fun clear() {
for (vm in map.values) {
vm.clear()
}
map.clear()
}
}
ViewModel.java
- 通过map管理内部的协程
- 通过Set管理内部的Closeable资源
- Activity销毁前会回调onCleared()
public abstract class ViewModel {
@Nullable
private final Map<String, Object> mBagOfTags = new HashMap<>();
@Nullable
private final Set<Closeable> mCloseables = new LinkedHashSet<>();
private volatile boolean mCleared = false;
public ViewModel() {
}
public ViewModel(@NonNull Closeable... closeables) {
mCloseables.addAll(Arrays.asList(closeables));
}
public void addCloseable(@NonNull Closeable closeable) {
if (mCloseables != null) {
synchronized (mCloseables) {
mCloseables.add(closeable);
}
}
}
@SuppressWarnings("WeakerAccess")
protected void onCleared() {
}
@MainThread
final void clear() {
mCleared = true;
if (mBagOfTags != null) {
synchronized (mBagOfTags) {
for (Object value : mBagOfTags.values()) {
// see comment for the similar call in setTagIfAbsent
closeWithRuntimeException(value);
}
}
}
// We need the same null check here
if (mCloseables != null) {
synchronized (mCloseables) {
for (Closeable closeable : mCloseables) {
closeWithRuntimeException(closeable);
}
}
}
onCleared();
}
@SuppressWarnings("unchecked")
<T> T setTagIfAbsent(String key, T newValue) {
T previous;
synchronized (mBagOfTags) {
previous = (T) mBagOfTags.get(key);
if (previous == null) {
mBagOfTags.put(key, newValue);
}
}
T result = previous == null ? newValue : previous;
if (mCleared) {
closeWithRuntimeException(result);
}
return result;
}
@SuppressWarnings({"TypeParameterUnusedInFormals", "unchecked"})
<T> T getTag(String key) {
if (mBagOfTags == null) {
return null;
}
synchronized (mBagOfTags) {
return (T) mBagOfTags.get(key);
}
}
private static void closeWithRuntimeException(Object obj) {
if (obj instanceof Closeable) {
try {
((Closeable) obj).close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
ViewModel.kt
新增扩展属性viewModelScope,其是一个CoroutineScope
private const val JOB_KEY = "androidx.lifecycle.ViewModelCoroutineScope.JOB_KEY"
public val ViewModel.viewModelScope: CoroutineScope
get() {
val scope: CoroutineScope? = this.getTag(JOB_KEY)
if (scope != null) {
return scope
}
return setTagIfAbsent(
JOB_KEY,
CloseableCoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
)
}
internal class CloseableCoroutineScope(context: CoroutineContext) : Closeable, CoroutineScope {
override val coroutineContext: CoroutineContext = context
override fun close() {
coroutineContext.cancel()
}
}
ViewModelProvider
- 最终调用3参构造函数初始化ViewModelStore、Factory、CreationExtras
- defaultFactory()/defaultCreationExtras()先判断当前ViewModelStore是否是HasDefaultViewModelProviderFactory,若是则调用提供的默认工厂/参数,否则使用NewInstanceFactory/CreationExtras.Empty
- get()根据全限定类名判断ViewModelStore是否已经创建,若是则直接返回,否则通过Factory和CreationExtras创建并存储到ViewModelStore的map中
public open class ViewModelProvider
@JvmOverloads
constructor(
private val store: ViewModelStore,
private val factory: Factory,
private val defaultCreationExtras: CreationExtras = CreationExtras.Empty,
) {
public interface Factory {
public fun <T : ViewModel> create(modelClass: Class<T>): T {
throw UnsupportedOperationException(
"Factory.create(String) is unsupported. This Factory requires " +
"`CreationExtras` to be passed into `create` method."
)
}
public fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T =
create(modelClass)
companion object {
@JvmStatic
fun from(vararg initializers: ViewModelInitializer<*>): Factory =
InitializerViewModelFactory(*initializers)
}
}
public constructor(
owner: ViewModelStoreOwner
) : this(owner.viewModelStore, defaultFactory(owner), defaultCreationExtras(owner))
public constructor(owner: ViewModelStoreOwner, factory: Factory) : this(
owner.viewModelStore,
factory,
defaultCreationExtras(owner)
)
@MainThread
public open operator fun <T : ViewModel> get(modelClass: Class<T>): T {
val canonicalName = modelClass.canonicalName
?: throw IllegalArgumentException("Local and anonymous classes can not be ViewModels")
return get("$DEFAULT_KEY:$canonicalName", modelClass)
}
@Suppress("UNCHECKED_CAST")
@MainThread
public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T {
val viewModel = store[key]
if (modelClass.isInstance(viewModel)) {
return viewModel as T
} else {
@Suppress("ControlFlowWithEmptyBody")
if (viewModel != null) {
// TODO: log a warning.
}
}
val extras = MutableCreationExtras(defaultCreationExtras)
extras[VIEW_MODEL_KEY] = key
return try {
factory.create(modelClass, extras)
} catch (e: AbstractMethodError) {
factory.create(modelClass)
}.also { store.put(key, it) }
}
@Suppress("SingletonConstructor")
public open class NewInstanceFactory : Factory {
@Suppress("DocumentExceptions")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return try {
modelClass.getDeclaredConstructor().newInstance()
} catch (e: NoSuchMethodException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
} catch (e: InstantiationException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
} catch (e: IllegalAccessException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
}
}
public companion object {
private var sInstance: NewInstanceFactory? = null
@JvmStatic
public val instance: NewInstanceFactory
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
get() {
if (sInstance == null) {
sInstance = NewInstanceFactory()
}
return sInstance!!
}
private object ViewModelKeyImpl : Key<String>
@JvmField
val VIEW_MODEL_KEY: Key<String> = ViewModelKeyImpl
}
}
}
internal fun defaultCreationExtras(owner: ViewModelStoreOwner): CreationExtras {
return if (owner is HasDefaultViewModelProviderFactory) {
owner.defaultViewModelCreationExtras
} else CreationExtras.Empty
}
ViewModel 的生命周期

ViewModel不受Configuration改变影响生命周期,当ComponentActivity结束时会回调onCleared()
public ComponentActivity() {
......
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();
}
.......
}
}
});
......
}
997

被折叠的 条评论
为什么被折叠?



