Android Jetpack架構組件 ViewModel詳解
前言
前面兩篇文章我們已經學習了Lifecycle和DataBind,本篇文章我們來學習Jetpack系列中比較重要的ViewModel,Jetpack的很多很多組件都是搭配使用的,所以單獨的知識點可能會有些”無意義“但卻是我們項目實戰的基礎!
ViewModel的使用
ViewModel類旨在以注重生命周期的方式存儲和管理界面相關的數據。ViewModel類讓數據可在發生屏幕旋轉等配置更改后繼續存在。這句話很好理解,還記得我們在講解Lifecycle的時候 舉的例子嗎,我們還是使用那個例子,如果你還沒看過,可移步至:
Android Jetpack系列之Lifecycle
我們再回顧一次需求:
在Activity 可見的時候,我們去做一個計數功能,每隔一秒 將計數加1 ,當Activity不可見的時候停止計數,當Activity被銷毀的時候 將計數置為0,這里我們在Activity被銷毀的時候不再將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() { }}
我們運行程序,在計數的過程中 使屏幕旋轉,運行結果如下所示:
我們可以看到,當屏幕旋轉的時候,由于生命周期發生了改變,導致數據被銷毀,所以計數器的計數又從初始值開始計數了,那么我們如何解決這個問題呢,你肯定會說,緩存呀,重寫onSabeInstanceState()方法等等,都可以但是都不夠優雅,那么如何優雅的來解決這個問題呢,這就是我們的今天的主角 ViewModel。
ViewModel的使用
我們新建Main3ActivityModel 繼承自 ViewModel,在Main3ActivityModel中定義count變量 如下所示:
public class Main3ActivityViewModel extends ViewModel { public int count = 0; }
沒錯,就是這么簡單,我們只要保證計數的變量是這個model中的變量,就可以解決我們上面的問題
我們通過ViewModelProviders來獲取ViewModel對象
main3ActivityViewModel = ViewModelProviders.of(this).get(Main3ActivityViewModel.class);
但是這個方法已經過時了,替代方法是
main3ActivityViewModel = new ViewModelProvider(this).get(Main3ActivityViewModel.class);
為了讓WorkUtil使用Model中的變量,所以我們要將ViewModel 傳遞過去,在WorkUtil中新增一個構造方法
private Main3ActivityViewModel main3ActivityViewModel; public WorkUtil(Main3ActivityViewModel main3ActivityViewModel) { this.main3ActivityViewModel = main3ActivityViewModel;}
我們將WorkUtil中的計數變量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));
再次運行程序,運行過程中旋轉手機屏幕,打印如下所示:
我們可以看到,在屏幕旋轉之后,計數器的計數保留了,那么viewModel是如何做到的呢,這是因為ViewModel 對象存在的時間比視圖或 LifecycleOwners 的特定實例存在的時間更長,ViewModel的生命周期如下圖所示(摘自官網)
向ViewModel傳參
當前計數的需求是從0開始計時,我們現在修改需求如下,使用用戶輸入的數字為起點開始計數,這樣的話ViewModel中的count就不是0了,而是傳入的參數,我們在Main3Activity中定義變量inputCount 來模擬用戶輸入的數字
private int inputCount = 100;
在Main3ViewModel中添加構造方法
public int count = 0; public Main3ActivityViewModel(int count) { this.count = count;}
看到這里,你可能會說,我們直接new一個傳過去不就行了嗎,請記住這是萬萬不行的,因為如果我們使用直接實例化來創建ViewModel,那么ViewModel的生命周期就受Activity的影響了,所以為什么我們只能通過ViewModelProvider來獲取ViewModel的實例。
我們需要借助ViewModelProvider.Factory來實現傳參,新建Main3ActivityViewModelFactor繼承自 ViewModelProvider.Factory,重寫其onCreate方法,如下所示:
public class Main3ActivityViewModelFactory implements ViewModelProvider.Factory { @NonNull @Override public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { return null; }}
添加一個構造方法,并在create中創建VideModel實例
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中獲取實例的時候 采用如下方法
main3ActivityViewModel = new ViewModelProvider(this,new Main3ActivityViewModelFactory(inputCount)).get(Main3ActivityViewModel.class);
運行程序,打印結果如下所示:
如此一來 我們就實現ViewModel傳遞參數了~
以上就是Android Jetpack架構組件 ViewModel詳解的詳細內容,更多關于Android Jetpack架構組件 ViewModel的資料請關注好吧啦網其它相關文章!
相關文章: