Android從零開始搭建MVVM架構(2)————ViewModel

在真正接觸並使用MVVM架構的時候,整個人都不好了。因爲個人覺得,MVVM相對於MVC、MVP學習難度比較大,設計的知識點不是一點半點。所以想慢慢記錄下自己的成長。如有錯誤希望指正。

從零開始搭建MVVM架構系列文章(持續更新):
Android從零開始搭建MVVM架構(1)————DataBinding
Android從零開始搭建MVVM架構(2)————ViewModel
Android從零開始搭建MVVM架構(3)————LiveData
Android從零開始搭建MVVM架構(4)————Room(從入門到進階)
Android從零開始搭建MVVM架構(5)————Lifecycles
Android從零開始搭建MVVM架構(6)————使用玩Android API帶你搭建MVVM框架(初級篇)
Android從零開始搭建MVVM架構(7) ———— 使用玩Android API帶你搭建MVVM框架(終極篇)

還是那張圖AAC(Android Architecture Components)

這篇我們講ViewModel。這裏我們只是簡單瞭解和人事MVVM中的ViewModel。等把這些組件都認識後,我們再以wanAndroid api擼一遍正題的MVVM項目。


一、ViewModel

還記得MVP中的Model嗎。這裏的ViewModel有點類似MVP中的Model的作用。但是google出了一套AAC組件。這些組件讓開發者能開發高效的項目。其中ViewModel也是其中組件之一。

1.1、爲什麼會有這個ViewModel組件

簡介:ViewModel是以生命週期的方式存儲與管理UI相關數據
作用
1、在MVVM模式中,使Model與View分離
2、負責爲ui準備數據
3、存儲數據

這裏最大的亮點是以生命週期的方式。舉例:假如在Activity裏使用。他會貫穿整個Activity裏的生命週期。先看張圖:

首先把結果先總結以下幾點(後面用例子驗證):

  • ViewModel只會在Activity存活,且只會創建一次。當銷燬時,會主動調用onClered。

爲什麼整個生命週期方式很重要?例如:app需要頻繁異步請求數據,比如請求網絡調接口,這些都是相當耗時。比如Activity被銷燬後接口請求才返回,考慮到內存泄漏情況,會給我們增添好多複雜工作。但現在我們利用ViewModel處理數據回調,可以解決此問題。意思只要繼承我們的ViewModel後,可能會出現的bug,google都幫我們處理了。

  • 因爲在Activity存活時,只創建一次,那麼在此Activity下的所有Fragment都可以共享一個ViewModel
  • 由於 ViewModel 生命週期可能長與 activity 生命週期,所以爲了避免內存泄漏Google禁止在ViewModel中持有Context或activity或view的引用。如果非得使用Context,
    可以繼承AndroidViewModel 類中獲取ApplicationContext
  • 之前我們在activity銷燬重建時,可以用activity的onSaveInstanceState()機制保存和恢復數據,但缺點明顯,
    只適合保存少量的可以被序列化、反序列化的數據。假如我們需要保存一個比較大的數據,這個時候ViewModel就可以實現。


怎麼看上面的生命週期圖呢

1、Activity created(走了3個生命週期),對應於ViewModel的scope。

2、Activity rorared(類似切換了橫豎屏幕),還是對應scope

3、finish()(Activity銷燬),依賴是scope

4、Finished (已經銷燬了)。調用ViewModel的onCleared。

這樣說很模糊,看一下例子


二、探索ViewModel的生命週期

我們首先創建我們的MyViewModel,繼承ViewModel。並重寫onCleared()

public class MyViewModel extends ViewModel {
    @Override
    protected void onCleared() {
        super.onCleared();
        LogUtils.i("MyViewModel的相關","Activity被殺死後也會被銷燬!");
    }
}

點開ViewModel的源碼:


因爲這層沒有透露出具體的生命週期綁定和銷燬的具體實現。我們還要去找實現類。這裏我們本着簡單使用的原則,那麼我就直接在Activity裏打印MyViewModel的hashCode值來驗證上面的圖,Activity裏的代碼。這裏還要說下,這裏我們用到了ViewModelProciders類,所以要引入下依賴

implementation ‘android.arch.lifecycle:extensions:1.1.1’

public class ViewModelActivity extends FragmentActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_viewmodel);
        MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
        LogUtils.i("MyViewModel的相關", "onCreate ==> " + myViewModel.hashCode());
    }

    @Override
    protected void onStart() {
        super.onStart();
        MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
        LogUtils.i("MyViewModel的相關", "onStart ==> " + myViewModel.hashCode());
    }

    @Override
    protected void onResume() {
        super.onResume();
        MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
        LogUtils.i("MyViewModel的相關", "onResume ==> " + myViewModel.hashCode());
    }

    @Override
    protected void onPause() {
        super.onPause();
        MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
        LogUtils.i("MyViewModel的相關", "onPause ==> " + myViewModel.hashCode());
    }

    @Override
    protected void onStop() {
        super.onStop();
        MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
        LogUtils.i("MyViewModel的相關", "onStop ==> " + myViewModel.hashCode());
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
        LogUtils.i("MyViewModel的相關", "onDestroy ==> " + myViewModel.hashCode());
    }
}

運行項目後,看打印;這裏可以看到,hashCode值都是一樣的。:

接着我們讓手機橫豎切換下,看打印。同樣可以看到hashCode值是一樣的,沒有改變:

最後,我們退出這個頁面,看打印。這裏在調用了ViewModel的onCleared後銷燬後,hashCode值才重新創建。這裏唯一疑點是,這裏和官網圖有些不同,ViewModel的銷燬onClered,在Ondestroy的前一步(只是和圖解效果有差異,但是流程是對的,如有小夥伴對這塊熟悉,請指點下):


三、與Fragment間共享數據

比如我們Activity裏還展示了很多個Fragment。我們這裏只需要看一段Fragment裏的代碼就清楚了

//從getActivity()這句,那可不是同一個MyViewModel嗎。
ViewModelProviders.of(getActivity()).get(MyViewModel.class)

至此這裏對簡單的ViewModel做了簡單介紹,和使用。讓我們一起慢慢實現自己的MVVM框架把!!

本文demo地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章