簡介
背景
這幾年 MVP 架構(gòu)在安卓界非常流行媒吗,幾乎已經(jīng)成為主流框架念搬,它讓業(yè)務(wù)邏輯 和 UI操作相對獨(dú)立瓷产,使得代碼結(jié)構(gòu)更清晰。
MVVM 在前端火得一塌糊涂吱窝,而在安卓這邊卻基本沒見到幾個人在用讥邻,看到介紹 MVVM 也最多是講 DataBinding 或 介紹思想的迫靖。偶爾看到幾篇提到應(yīng)用的院峡,還是對谷歌官網(wǎng)的Architecture Components 文章的翻譯。
相信大家看別人博客或官方文檔的時候系宜,總會碰到一些坑照激。要么入門教程寫得太復(fù)雜(無力吐槽,前面寫一堆原理盹牧,各種高大上的圖俩垃,然并卵,到實(shí)踐部分一筆帶過汰寓,你確定真的是入門教程嗎)口柳。要么就是簡單得就是一個 hello world,然后就沒有下文了(看了想罵人)有滑。
實(shí)在看不下去的我跃闹,決定插手你的人生。
目錄
《安卓-深入淺出MVVM教程》大致分兩部分:應(yīng)用篇、原理篇望艺。
采用循序漸進(jìn)方式苛秕,內(nèi)容深入淺出,符合人類學(xué)習(xí)規(guī)律找默,希望大家用最少時間掌握 MVVM艇劫。
應(yīng)用篇:
01 Hello MVVM (快速入門)
02 Repository (數(shù)據(jù)倉庫)
03 Cache (本地緩存)
04 State Lcee (加載/空/錯誤/內(nèi)容視圖)
05 Simple Data Source (簡單的數(shù)據(jù)源)
06 Load More (加載更多)
07 DataBinding (數(shù)據(jù)與視圖綁定)
08 RxJava2
09 Dragger2
10 Abstract (抽象)
11 Demo (例子)
12-n 待定(歡迎 github 提建議)
原理篇
01 MyLiveData(最簡單的LiveData)
02-n 待定(并不是解讀源碼,那樣太無聊了惩激,打算帶你從0擼一個 Architecture)
關(guān)于提問
本人水平和精力有限店煞,如果有大佬發(fā)現(xiàn)哪里寫錯了或有好的建議,歡迎在本教程附帶的 github倉庫 提issue风钻。
What浅缸?為什么不在博客留言?考慮到國內(nèi)轉(zhuǎn)載基本無視版權(quán)的情況魄咕,一般來說你都不是在源出處看到這篇文章衩椒,所以留言我也一般是看不到的。
教程附帶代碼
https://github.com/ittianyu/MVVM
應(yīng)用篇放在 app 模塊下哮兰,原理篇放在 implementation 模塊下毛萌。
每一節(jié)代碼采用不同包名,相互獨(dú)立喝滞。
前言
上一篇阁将,介紹了 MVVM 的常見用法。
這一篇將會從零開始構(gòu)建 MVVM 的基礎(chǔ)類庫右遭。
怎么實(shí)現(xiàn) View 和 ViewModel 的綁定做盅?
拋開上一篇講得內(nèi)容,現(xiàn)在問題如上窘哈,你會怎么設(shè)計(jì)吹榴?
降低難度,假設(shè)我們先不考慮生命周期和其他因素滚婉,究竟怎么樣才能實(shí)現(xiàn) ViewModel改變時通知view图筹,view操作時通知ViewModel?
通過展開問題让腹,發(fā)現(xiàn)可以轉(zhuǎn)化為兩個問題远剩,采用分治思想
view操作時通知ViewModel
這個很簡單,和我們平時做開發(fā)時一樣的思路骇窍,添加 UI 事件監(jiān)聽瓜晤,觸發(fā)之后,主動去調(diào)用 ViewModel腹纳。(可能這思想不太準(zhǔn)確痢掠,簡單起見哈恰,先這樣理解吧,后面再糾正)
ViewModel改變時通知view
那這個呢志群?難道是數(shù)據(jù)獲取成功時着绷,去調(diào)用 View?
那這就又回到之前MVP MVC 的思路了锌云。
MVVM 的優(yōu)點(diǎn)是荠医,數(shù)據(jù)改動,自動反映到 View 上桑涎。也就是說彬向,不需要我們主動去操作 View。
既然主動不好攻冷,那就被動吧娃胆。(手動滑稽)
換句話說,是 View 主動去監(jiān)聽數(shù)據(jù)變化等曼,View 自己決定怎么響應(yīng)里烦,而不是被 ViewModle 推著走。
那答案就很明顯了禁谦,觀察者模式胁黑。
實(shí)現(xiàn)
雖然思路知道了,但該從哪里開始寫 LiveData 呢州泊?
最快的辦法是需要什么寫什么丧蘸。
需求
所以這里快速寫一個簡單的案例:
界面中只有一個 TextView,點(diǎn)擊屏幕給 TextView 隨機(jī)設(shè)置一個0-1000的數(shù)字遥皂。
xml
請?jiān)试S我用 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 的傳入。也就是調(diào)用 ldName.observer
來監(jiān)聽數(shù)據(jù)的變化仇祭,記得在 onDestroy 時取消監(jiān)聽披蕉。
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 定義
這個時候代碼肯定是報錯的,上面是先用后實(shí)現(xiàn)乌奇,這樣就明確了 MyLiveData 公開的方法和功能。寫起來就很清晰了眯娱。
通過用法礁苗,我們就能定義出一個接口和一個類,目前都是空實(shí)現(xiàn)徙缴。
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 實(shí)現(xiàn)
最簡單的觀察者模式试伙,就是用個容器把監(jiān)聽器存起來嘁信,當(dāng)數(shù)據(jù)改變時,去調(diào)用監(jiān)聽器疏叨。
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);
}
}
總結(jié)
LiveData 就這么簡單潘靖?
當(dāng)然不是,我們現(xiàn)在寫的 LiveData 還需要手動取消監(jiān)聽蚤蔓。
而谷歌的 LiveData 卻不用卦溢。
所以下一步的目標(biāo)是逐步完善它。