欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android ViewModel的作用深入講解

 更新時(shí)間:2023年05月12日 08:44:27   作者:小明杰  
這篇文章主要介紹了Android ViewModel的作用,ViewModel類旨在以注重生命周期的方式存儲(chǔ)和管理界面相關(guān)數(shù)據(jù),ViewModel類讓數(shù)據(jù)可在發(fā)生屏幕旋轉(zhuǎn)等配置更改后繼續(xù)留存,需要詳細(xì)了解可以參考下文

ViewModel它的作用是什么呢

ViewModel 類旨在以注重生命周期的方式存儲(chǔ)和管理界面相關(guān)數(shù)據(jù)。ViewModel 類讓數(shù)據(jù)可在發(fā)生屏幕旋轉(zhuǎn)等配置更改后繼續(xù)留存(官方解釋)

看到這里我們就可以總結(jié)viewmodel的兩個(gè)作用點(diǎn),第一viewmodel在activity和fragment銷毀時(shí)自己也會(huì)被清除掉,第二點(diǎn)viewmodel在屏幕旋轉(zhuǎn)activity銷毀后重建可以顯示之前數(shù)據(jù)。

那么問題就來了viewmodel是怎么保存數(shù)據(jù)的以及自動(dòng)釋放掉內(nèi)存? 這兩個(gè)問題弄懂了viewmodel的面紗也就被我們揭開了。

那我們就直接從最簡單的使用viewmodel開始說起

class UserViewModel : ViewModel() {
    var age: Int = 0
}
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val userViewModel =
            ViewModelProvider(this, ViewModelProvider.NewInstanceFactory())[UserViewModel::class.java]
        val mView = ActivityMainBinding.inflate(layoutInflater)
        setContentView(mView.root)
        mView.tv.text = userViewModel.age.toString()
        var sum = 0
        mView.tv.setOnClickListener {
            sum = sum.inc()
            userViewModel.age = sum
        }
    }
}

隨著我們不停的點(diǎn)擊 sum會(huì)越來越大 當(dāng)我們旋轉(zhuǎn)屏幕的時(shí)候 activity會(huì)重建  但是我們獲取的age卻是最后一次點(diǎn)擊的值,這就證明了我們數(shù)據(jù)是被保存了下來。那么viewmodel是怎么做到的呢?我們從源碼角度去分析

以下源碼分析是從Android13分析的

看源碼viewmodel是一個(gè)抽象類,并不能看出什么。那么我們就得換一個(gè)思路去思考了。既然viewmodel是和activity有關(guān)系,而且在activity旋轉(zhuǎn)銷毀時(shí)還能做到復(fù)用,那么我們就從activity中去尋找。

一級(jí)一級(jí)尋找發(fā)現(xiàn)在ComponentActivity實(shí)現(xiàn)了一個(gè)ViewModelStoreOwner接口 看命名是和viewmodel有點(diǎn)關(guān)系看下這個(gè)接口內(nèi)部有什么

public interface ViewModelStoreOwner {
    /**
     * Returns owned {@link ViewModelStore}
     *
     * @return a {@code ViewModelStore}
     */
    @NonNull
    ViewModelStore getViewModelStore();
}
//代碼很簡潔 一個(gè)抽象方法 返回值ViewModelStore 顧名思義這個(gè)類的功能也就呼之欲出,存儲(chǔ)viewmodel,那我們就看實(shí)現(xiàn)類中怎么處理的
//ComponentActivity中實(shí)現(xiàn) 
  @NonNull
    @Override
    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;
    }
//我們直接看ensureViewModelStore()方法
void ensureViewModelStore() {
        if (mViewModelStore == null) {
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                // Restore the ViewModelStore from NonConfigurationInstances
                mViewModelStore = nc.viewModelStore;
            }
            if (mViewModelStore == null) {
                mViewModelStore = new ViewModelStore();
            }
        }
    }
 //ensureViewModelStore方法看來是為了獲取ViewModelStore,那我們?cè)诰唧w看下ViewModelStore內(nèi)部做了什么?
public class ViewModelStore {
    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());
    }
    /**
     *  Clears internal storage and notifies ViewModels that they are no longer used.
     */
    public final void clear() {
        for (ViewModel vm : mMap.values()) {
            vm.clear();
        }
        mMap.clear();
    }
}
//看到這里就明了了,果然和我們猜想的一樣,ViewModelStore是用來緩存ViewModel的

經(jīng)過我們分析已經(jīng)明白了viewmodel是被ViewModelStore緩存起來的,那么又是如何做到在activity不正常銷毀時(shí)去恢復(fù)數(shù)據(jù)的呢?

在ComponentActivity在發(fā)現(xiàn)還有另一個(gè)方法中使用了ViewModelStore

onRetainNonConfigurationInstance方法

public final Object onRetainNonConfigurationInstance() {
        // Maintain backward compatibility.
        Object custom = onRetainCustomNonConfigurationInstance();
        ViewModelStore viewModelStore = mViewModelStore;
        if (viewModelStore == null) {
            // No one called getViewModelStore(), so see if there was an existing
            // ViewModelStore from our last NonConfigurationInstance
            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;
    }

方法體內(nèi)的代碼也很容易理解 如果viewModelStore為null 就去給它賦值。那么這個(gè)方法是在什么時(shí)候執(zhí)行的呢?經(jīng)過一番debug發(fā)現(xiàn)在activity切換橫豎屏的時(shí)候 這個(gè)方法就被觸發(fā)了 而getViewModelStore方法在activity創(chuàng)建的時(shí)候就執(zhí)行了。我們現(xiàn)在知道了viewModelStore的創(chuàng)建時(shí)機(jī),那么viewmodel是如何存儲(chǔ)到viewModelStore中的呢?

還記得我們寫的示例代碼嗎?

  val userViewModel =
            ViewModelProvider(this, ViewModelProvider.NewInstanceFactory())
                .get(UserViewModel::class.java)

我們就從ViewModelProvider入手

 public constructor(owner: ViewModelStoreOwner, factory: Factory) : this(
        owner.viewModelStore,
        factory,
        defaultCreationExtras(owner)
    )

第一個(gè)入?yún)⒕褪俏覀僡ctivity實(shí)例 然后拿到我們自己的viewModelStore,這個(gè)時(shí)候的viewModelStore已經(jīng)創(chuàng)建好了,看第二個(gè)參數(shù)是Factory 我們傳遞的是NewInstanceFactory這個(gè)一看就是單例,內(nèi)部實(shí)現(xiàn)了一個(gè)create方法

  public open class NewInstanceFactory : Factory {
        @Suppress("DocumentExceptions")
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return try {
                modelClass.newInstance()
            } catch (e: InstantiationException) {
                throw RuntimeException("Cannot create an instance of $modelClass", e)
            } catch (e: IllegalAccessException) {
                throw RuntimeException("Cannot create an instance of $modelClass", e)
            }
        }

一個(gè)泛型方法返回一個(gè)自定義的viewmodel實(shí)例,但是還是沒看到如何存儲(chǔ)的viewmodel,別急

我們?cè)賮砜醋詈笳{(diào)用的get方法

 @MainThread
    public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): 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) }
    }

首選會(huì)從ViewModelStore中獲取viewmodel ,看if語句內(nèi)部就可以看出直接返回的是緩存的viewmodel,如果不存在則根據(jù)創(chuàng)建的factory去實(shí)例化viewmodel然后并存儲(chǔ)到ViewModelStore中。

經(jīng)過我們的源碼分析,我們現(xiàn)在已經(jīng)明白了viewmodel的存儲(chǔ)過程和如何在activity銷毀時(shí)獲取的流程。

那么viewmodel又是如何銷毀的呢?還記得viewmodel中的onCleared方法嗎?注釋就寫明了當(dāng)這個(gè)ViewModel不再使用并被銷毀時(shí),這個(gè)方法將被調(diào)用。 那么就來看這個(gè)方法在什么時(shí)候調(diào)用的

內(nèi)部有一個(gè)clear該方法又被ViewModelStore的clear方法調(diào)用,接著又被ComponentActivity內(nèi)部

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

用到了Lifecycle去監(jiān)聽生命周期當(dāng)activity不正常銷毀時(shí),則清除掉緩存的viewmodel。至此我們就搞懂了viewmodel是如何實(shí)現(xiàn)了對(duì)數(shù)據(jù)的存儲(chǔ)和以及數(shù)據(jù)的獲取。

這里還有一點(diǎn)需要額外說明,ViewModelStore也是從緩存中取得, 在getViewModelStore方法和onRetainNonConfigurationInstance方法中 都能看到getLastNonConfigurationInstance方法的身影。不為null,就獲取緩存的ViewModelStore,那就自然能獲取到之前存儲(chǔ)的viewModel 至于怎么緩存的各位大佬自己研究吧!

至此 ,我們已經(jīng)搞懂了viewmodel是如何做到在activity銷毀時(shí)自動(dòng)清除和銷毀重建顯示之前數(shù)據(jù)。

到此這篇關(guān)于Android ViewModel的作用深入講解的文章就介紹到這了,更多相關(guān)Android ViewModel內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論