Android Jetpack架構(gòu)組件 ViewModel詳解
前言
前面兩篇文章我們已經(jīng)學(xué)習(xí)了Lifecycle和DataBind,本篇文章我們來(lái)學(xué)習(xí)Jetpack系列中比較重要的ViewModel,Jetpack的很多很多組件都是搭配使用的,所以單獨(dú)的知識(shí)點(diǎn)可能會(huì)有些”無(wú)意義“但卻是我們項(xiàng)目實(shí)戰(zhàn)的基礎(chǔ)!
ViewModel的使用
ViewModel類(lèi)旨在以注重生命周期的方式存儲(chǔ)和管理界面相關(guān)的數(shù)據(jù)。ViewModel類(lèi)讓數(shù)據(jù)可在發(fā)生屏幕旋轉(zhuǎn)等配置更改后繼續(xù)存在。這句話(huà)很好理解,還記得我們?cè)谥v解Lifecycle的時(shí)候 舉的例子嗎,我們還是使用那個(gè)例子,如果你還沒(méi)看過(guò),可移步至:
Android Jetpack系列之Lifecycle
我們?cè)倩仡櫼淮涡枨螅?/p>
在Activity 可見(jiàn)的時(shí)候,我們?nèi)プ鲆粋€(gè)計(jì)數(shù)功能,每隔一秒 將計(jì)數(shù)加1 ,當(dāng)Activity不可見(jiàn)的時(shí)候停止計(jì)數(shù),當(dāng)Activity被銷(xiāo)毀的時(shí)候 將計(jì)數(shù)置為0,這里我們?cè)贏ctivity被銷(xiāo)毀的時(shí)候不再將count置為0,WorkUtil代碼如下所示:
public class WorkUtil implements LifecycleObserver { private static final String TAG = 'WorkUtil'; private boolean whetherToCount = true; private int count = 0; @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) public void start() { new Thread(new Runnable() { @Override public void run() { while (whetherToCount) { try { Thread.sleep(1000); count++; Log.d(TAG, 'start: ' + count); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) public void onStop() { whetherToCount = false; Log.d(TAG, 'onStop: '); } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) public void onDestory() { }}
我們運(yùn)行程序,在計(jì)數(shù)的過(guò)程中 使屏幕旋轉(zhuǎn),運(yùn)行結(jié)果如下所示:
我們可以看到,當(dāng)屏幕旋轉(zhuǎn)的時(shí)候,由于生命周期發(fā)生了改變,導(dǎo)致數(shù)據(jù)被銷(xiāo)毀,所以計(jì)數(shù)器的計(jì)數(shù)又從初始值開(kāi)始計(jì)數(shù)了,那么我們?nèi)绾谓鉀Q這個(gè)問(wèn)題呢,你肯定會(huì)說(shuō),緩存呀,重寫(xiě)onSabeInstanceState()方法等等,都可以但是都不夠優(yōu)雅,那么如何優(yōu)雅的來(lái)解決這個(gè)問(wèn)題呢,這就是我們的今天的主角 ViewModel。
ViewModel的使用
我們新建Main3ActivityModel 繼承自 ViewModel,在Main3ActivityModel中定義count變量 如下所示:
public class Main3ActivityViewModel extends ViewModel { public int count = 0; }
沒(méi)錯(cuò),就是這么簡(jiǎn)單,我們只要保證計(jì)數(shù)的變量是這個(gè)model中的變量,就可以解決我們上面的問(wèn)題
我們通過(guò)ViewModelProviders來(lái)獲取ViewModel對(duì)象
main3ActivityViewModel = ViewModelProviders.of(this).get(Main3ActivityViewModel.class);
但是這個(gè)方法已經(jīng)過(guò)時(shí)了,替代方法是
main3ActivityViewModel = new ViewModelProvider(this).get(Main3ActivityViewModel.class);
為了讓W(xué)orkUtil使用Model中的變量,所以我們要將ViewModel 傳遞過(guò)去,在WorkUtil中新增一個(gè)構(gòu)造方法
private Main3ActivityViewModel main3ActivityViewModel; public WorkUtil(Main3ActivityViewModel main3ActivityViewModel) { this.main3ActivityViewModel = main3ActivityViewModel;}
我們將WorkUtil中的計(jì)數(shù)變量count 改為 main3ActivityViewModel.count,如下所示:
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)public void start() { new Thread(new Runnable() { @Override public void run() { while (whetherToCount) { try { Thread.sleep(1000); main3ActivityViewModel.count++; Log.d(TAG, 'start: ' + main3ActivityViewModel.count); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start();}
main3Activity中在lifecycle中傳參:
getLifecycle().addObserver(new WorkUtil(main3ActivityViewModel));
再次運(yùn)行程序,運(yùn)行過(guò)程中旋轉(zhuǎn)手機(jī)屏幕,打印如下所示:
我們可以看到,在屏幕旋轉(zhuǎn)之后,計(jì)數(shù)器的計(jì)數(shù)保留了,那么viewModel是如何做到的呢,這是因?yàn)閂iewModel 對(duì)象存在的時(shí)間比視圖或 LifecycleOwners 的特定實(shí)例存在的時(shí)間更長(zhǎng),ViewModel的生命周期如下圖所示(摘自官網(wǎng))
向ViewModel傳參
當(dāng)前計(jì)數(shù)的需求是從0開(kāi)始計(jì)時(shí),我們現(xiàn)在修改需求如下,使用用戶(hù)輸入的數(shù)字為起點(diǎn)開(kāi)始計(jì)數(shù),這樣的話(huà)ViewModel中的count就不是0了,而是傳入的參數(shù),我們?cè)贛ain3Activity中定義變量inputCount 來(lái)模擬用戶(hù)輸入的數(shù)字
private int inputCount = 100;
在Main3ViewModel中添加構(gòu)造方法
public int count = 0; public Main3ActivityViewModel(int count) { this.count = count;}
看到這里,你可能會(huì)說(shuō),我們直接new一個(gè)傳過(guò)去不就行了嗎,請(qǐng)記住這是萬(wàn)萬(wàn)不行的,因?yàn)槿绻覀兪褂弥苯訉?shí)例化來(lái)創(chuàng)建ViewModel,那么ViewModel的生命周期就受Activity的影響了,所以為什么我們只能通過(guò)ViewModelProvider來(lái)獲取ViewModel的實(shí)例。
我們需要借助ViewModelProvider.Factory來(lái)實(shí)現(xiàn)傳參,新建Main3ActivityViewModelFactor繼承自 ViewModelProvider.Factory,重寫(xiě)其onCreate方法,如下所示:
public class Main3ActivityViewModelFactory implements ViewModelProvider.Factory { @NonNull @Override public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { return null; }}
添加一個(gè)構(gòu)造方法,并在create中創(chuàng)建VideModel實(shí)例
private int count; public Main3ActivityViewModelFactory(int count) { this.count = count;} @NonNull@Overridepublic <T extends ViewModel> T create(@NonNull Class<T> modelClass) { return (T) new Main3ActivityViewModel(count);}
在Activity中獲取實(shí)例的時(shí)候 采用如下方法
main3ActivityViewModel = new ViewModelProvider(this,new Main3ActivityViewModelFactory(inputCount)).get(Main3ActivityViewModel.class);
運(yùn)行程序,打印結(jié)果如下所示:
如此一來(lái) 我們就實(shí)現(xiàn)ViewModel傳遞參數(shù)了~
以上就是Android Jetpack架構(gòu)組件 ViewModel詳解的詳細(xì)內(nèi)容,更多關(guān)于Android Jetpack架構(gòu)組件 ViewModel的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!
相關(guān)文章:
1. ASP中解決“對(duì)象關(guān)閉時(shí),不允許操作。”的詭異問(wèn)題……2. 淺談CSS不規(guī)則邊框的生成方案3. 基于javaweb+jsp實(shí)現(xiàn)學(xué)生宿舍管理系統(tǒng)4. CSS百分比padding制作圖片自適應(yīng)布局5. 詳解盒子端CSS動(dòng)畫(huà)性能提升6. html中的form不提交(排除)某些input 原創(chuàng)7. jsp實(shí)現(xiàn)簡(jiǎn)單用戶(hù)7天內(nèi)免登錄8. 5個(gè)HTML5的常用本地存儲(chǔ)方式詳解與介紹9. CSS可以做的幾個(gè)令你嘆為觀止的實(shí)例分享10. asp在iis7報(bào)錯(cuò)行號(hào)不準(zhǔn)問(wèn)題的解決方法
