安卓MVVM教程MyLiveData最簡單的LiveData

安卓MVVM教程MyLiveData最簡單的LiveData

來自專欄極樂科技8 人贊了文章

背景

這幾年 MVP 架構在安卓屆非常流行,幾乎已經成為主流框架,它讓業務邏輯 和 UI操作相對獨立,使得代碼結構更清晰。

MVVM 在前端火得一塌糊塗,而在安卓這邊卻基本沒見到幾個人在用,看到介紹 MVVM 也最多是講 DataBinding 或 介紹思想的。偶爾看到幾篇提到應用的,還是對谷歌官網的Architecture Components 文章的翻譯。

相信大家看別人博客或官方文檔的時候,總會碰到一些坑。要麼入門教程寫得太複雜(無力吐槽,前面寫一堆原理,各種高大上的圖,然並卵,到實踐部分一筆帶過,你確定真的是入門教程嗎)。要麼就是簡單得就是一個 hello world,然後就沒有下文了(看了想罵人)。

實在看不下去的我,決定插手你的人生。

降低難度,假設我們先不考慮生命周期和其他因素,究竟怎麼樣才能實現 ViewModel改變時通知view,view操作時通知ViewModel?

通過展開問題,發現可以轉化為兩個問題,採用分治思想

view操作時通知ViewModel

這個很簡單,和我們平時做開發時一樣的思路,添加 UI 事件監聽,觸發之後,主動去調用 ViewModel。(可能這思想不太準確,簡單起見,先這樣理解吧,後面再糾正)

ViewModel改變時通知view

那這個呢?難道是數據獲取成功時,去調用 View?

那這就又回到之前MVP MVC 的思路了。

MVVM 的優點是,數據改動,自動反映到 View 上。也就是說,不需要我們主動去操作 View。

既然主動不好,那就被動吧。(手動滑稽)

換句話說,是 View 主動去監聽數據變化,View 自己決定怎麼響應,而不是被 ViewModle 推著走。

那答案就很明顯了,觀察者模式。

實現

雖然思路知道了,但該從哪裡開始寫 LiveData 呢?

最快的辦法是需要什麼寫什麼。

需求

所以這裡快速寫一個簡單的案例:

界面中只有一個 TextView,點擊屏幕給 TextView 隨機設置一個0-1000的數字。

xml

請允許我用 2 秒寫完這個界面

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/v_root" android:layout_width_="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <TextView android:id="@+id/tv_name" android:layout_width_="wrap_content" android:layout_height="wrap_content" android:text="name" /> </LinearLayout>

MyLiveDataActivity

參照上一篇的用法,很容易寫出這樣的代碼。

和之前比,這裡直接使用 LiveData,並且省略了 lifecycle 的傳入。也就是調用 ldName.observer 來監聽數據的變化,記得在 onDestroy 時取消監聽。

public class MyLiveDataActivity extends AppCompatActivity { private MyLiveData<String> ldName; private TextView tvName; private View vRoot; private OnValueChangeListener<String> nameObserver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initView(); initData(); initEvent(); } @Override protected void onDestroy() { super.onDestroy(); ldName.unobserver(nameObserver); } private void initView() { setContentView(R.layout.a_my_livedata); tvName = (TextView) findViewById(R.id.tv_name); vRoot = findViewById(R.id.v_root); } private void initData() { ldName = new MyLiveData<>(); nameObserver = new OnValueChangeListener<String>() { @Override public void onChange(String value) { tvName.setText(value); } }; ldName.observer(nameObserver); } private void initEvent() { vRoot.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { resetValue(); } }); } private void resetValue() { int randomInt = (int) (Math.random() * 1000); ldName.setValue(randomInt + ""); } }

MyLiveData 定義

這個時候代碼肯定是報錯的,上面是先用後實現,這樣就明確了 MyLiveData 公開的方法和功能。寫起來就很清晰了。

通過用法,我們就能定義出一個介面和一個類,目前都是空實現。

public interface OnValueChangeListener<T> { void onChange(T value); } public class MyLiveData<T> { public void observer(OnValueChangeListener<T> observer) { } public void unobserver(OnValueChangeListener<T> observer) { } public void setValue(T value) { } }

MyLiveData 實現

最簡單的觀察者模式,就是用個容器把監聽器存起來,當數據改變時,去調用監聽器。

public class MyLiveData<T> { private List<OnValueChangeListener<T>> observers = new ArrayList<>(); public void observer(OnValueChangeListener<T> observer) { observers.add(observer); } public void setValue(T value) { for (OnValueChangeListener<T> listener :observers) { listener.onChange(value); } } public void unobserver(OnValueChangeListener<T> observer) { observers.remove(observer); } }

總結

LiveData 就這麼簡單?

當然不是,我們現在寫的 LiveData 還需要手動取消監聽。

而谷歌的 LiveData 卻不用。

所以下一步的目標是逐步完善它。


推薦閱讀:

是否有可能在未來的某一天,安卓由於失敗的軟體生態圈而衰落,而wp憑藉著高質量的生態圈和流暢性超越他?
BAT哪家Android的APP 水準最高?
現在有哪些型號的電視支持airplay同屏播放?
最簡潔輕便快速的android 逆向分析工具--GDA
Xix.ai可以幫你在安卓手機上節省更多時間

TAG:Android | Android開發 | 人工智慧 |