轉(zhuǎn)載請(qǐng)標(biāo)明出處http://www.reibang.com/p/7fe5c2f9459a
前言:在上一篇http://www.reibang.com/p/fb8d33168f57中說(shuō)到要把MVVM的坑補(bǔ)上算吩。哪有跳過(guò)MVVM學(xué)DataBinding就算的道理。
但是由于日常工作任務(wù)以及個(gè)人的緣故,拖了半個(gè)月摇展。經(jīng)過(guò)一段時(shí)間的學(xué)習(xí)沦补,才發(fā)現(xiàn)DataBinding是構(gòu)建MVVM的工具鸟悴。
很早以前就使用的MVC過(guò)于耦合掏击,Activity十分臃腫棍厌。MVP模式雖然解決了MVC耦合的問(wèn)題盆繁,但是對(duì)象持有的內(nèi)存泄露掀淘,和V層一定程度耦合,以及P層接口過(guò)多代碼臃腫油昂。都是潛在的問(wèn)題革娄,日常開(kāi)發(fā)中經(jīng)常可見(jiàn)冕碟。相較之下拦惋,學(xué)習(xí)了MVVM就一個(gè)感覺(jué),真香安寺。
1.MVVM是什么
MVVM是Model-View-ViewModel的簡(jiǎn)寫(xiě)架忌。最早是Web開(kāi)發(fā)的概念,它本質(zhì)上就是MVC 的改進(jìn)版我衬。MVVM 就是將其中的View 的狀態(tài)和行為抽象化叹放,讓我們將視圖 UI 和業(yè)務(wù)邏輯分開(kāi)。由ViewModel進(jìn)行數(shù)據(jù)邏輯的處理挠羔,View專(zhuān)注視圖UI井仰。Model和傳統(tǒng)意義的model有些許不同,這里不止是指實(shí)體對(duì)象破加,還包括了數(shù)據(jù)的獲取俱恶,存儲(chǔ)。MVVM是由數(shù)據(jù)驅(qū)動(dòng)UI的范舀,且ViewModel可復(fù)用合是,View和ViewModel之間十分解耦,可以在日常工作中分開(kāi)編寫(xiě)锭环。
2.MVVM的使用
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:24.2.0'
implementation "android.arch.lifecycle:extensions:1.1.0"
}
這里會(huì)用到lifecycle組件聪全,lifecycle是Google提供的應(yīng)用組件生命周期管理組件。簡(jiǎn)單來(lái)說(shuō)辅辩,它可以很好的對(duì)activity难礼,F(xiàn)ragment等的生命周期進(jìn)行監(jiān)控管理娃圆,從而很好的避免內(nèi)存泄漏甚至崩潰。官方文檔中也有描述蛾茉。3.MVVM中的框架搭建
3.1ViewModel
官方提供了ViewModel類(lèi)供我們繼承讼呢。viewmodel是貫穿于整個(gè)activity生命周期的,只有activity銷(xiāo)毀之后谦炬,viewmodel生命周期才結(jié)束悦屏。ViewModel只關(guān)注數(shù)據(jù)業(yè)務(wù)邏輯,ViewModel中不做視圖相關(guān)的操作键思,更不持有控件引用窜管。通常會(huì)搭配LiveData來(lái)使用,下面會(huì)提及稚机。
public class UserViewModel extends ViewModel {
}
如果你在viewmodel中需要用到上下文,可以繼承AndroidViewModel获搏。
public class UserViewModel extends AndroidViewModel {
public UserViewModel(@NonNull Application application) {
super(application);
}
}
通常赖条,是使用DataBinding的ObservableFields(實(shí)現(xiàn)了BaseObservable)實(shí)現(xiàn)對(duì)象可觀(guān)察的。
public class UserViewModel extends AndroidViewModel {
ObservableField<User> liveDataUser = new ObservableField<>();
}
但是更多的我們會(huì)使用LiveData常熙,LiveData能實(shí)現(xiàn)對(duì)象觀(guān)察纬乍,還可以感知組件生命周期,ObservableFields則需要自己根據(jù)DataBinding手動(dòng)處理生命周期問(wèn)題裸卫。且LiveData可以主動(dòng)調(diào)用postValue仿贬,setValue通知UI,且LiveData可以更好的許多架構(gòu)組件 (如Room墓贿、WorkManager) 相互配合使用茧泪。這個(gè)在Google Android開(kāi)發(fā)者官方賬號(hào)也有提到。我們?cè)趘iewmodel中使用LiveData聋袋,然后在view中配合LiveData的observe方法队伟,即可觀(guān)察數(shù)據(jù)變化。
public class UserViewModel extends AndroidViewModel {
MutableLiveData<User> liveDataUser = new MutableLiveData<>();
public UserViewModel(@NonNull Application application) {
super(application);
}
public LiveData<User> Login() {
//vm傾向于對(duì)數(shù)據(jù)的處理,而不是對(duì)于view的處理
UserBiz userBiz = new UserBiz();
//例如數(shù)據(jù)層網(wǎng)絡(luò)請(qǐng)求操作
userBiz.Login("基佬2", new ILoginListener() {
@Override
public void onSuccess(User user) {
liveDataUser.postValue(user);
}
@Override
public void onFail() {
}
});
return liveDataUser;
}
}
3.2View
這里activity就是我們真正意義上的View幽勒,并且View并不在意數(shù)據(jù)業(yè)務(wù)邏輯嗜侮,不操作不處理數(shù)據(jù),他只在乎UI該做的事情啥容。
public class MainActivity extends AppCompatActivity {
private UserViewModel mNameViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// mNameViewModel.getUsers().observe(this, new Observer<List<User>>() {
// @Override
// public void onChanged(List<User> users) {
// }
// });
mNameViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
mNameViewModel.Login().observe(this, (User users) -> {
//我們更傾向于讓activity專(zhuān)注于視圖的處理锈颗,而不是對(duì)于數(shù)據(jù)的處理。
//訂閱LiveData中User列表數(shù)據(jù)變化咪惠,以lambda形式定義Observer,進(jìn)行監(jiān)聽(tīng)
Toast.makeText(this, "加載成功:"+users.toString(), Toast.LENGTH_SHORT).show();
});
}
}
像這樣击吱,View就可以通過(guò)ViewModelProviders找到你的ViewModel,調(diào)用方法且通過(guò)上文提到的LiveData監(jiān)聽(tīng)訂閱遥昧。在View里只做View的事情姨拥,不涉及數(shù)據(jù)绅喉。
3.3Model
這里Model不單是實(shí)體模型,還包括了網(wǎng)絡(luò)請(qǐng)求叫乌,服務(wù)等柴罐。是對(duì)數(shù)據(jù)的獲取,存儲(chǔ)的操作的憨奸。
public class UserBiz implements IUserBiz {
@Override
public void Login(String name, ILoginListener loginListener) {
User user = new User();
//模擬網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
user.setName(name);
user.setAge("18歲2");
user.setGender("男2");
loginListener.onSuccess(user);
}
}).start();
}
}
最終就可以實(shí)現(xiàn)5S后彈出toast的效果革屠。甚至,如果你想達(dá)到databinding的雙向綁定排宰,只需要activityMainBinding.setLifecycleOwner()即可似芝。一樣可以實(shí)現(xiàn)。
4.思考
學(xué)到這可以發(fā)現(xiàn)在MVVM板甘,是離不開(kāi)LiveData對(duì)于視圖數(shù)據(jù)的綁定的党瓮。但是對(duì)比前面學(xué)習(xí)的DataBinding,ObservableField都可以實(shí)現(xiàn)雙向綁定盐类。
4.1雙向綁定和生命周期
DataBinding可以使用ObservableField實(shí)現(xiàn)數(shù)據(jù)觀(guān)察寞奸,但LiveData通過(guò)activityMainBinding.setLifecycleOwner(this)也能實(shí)現(xiàn)雙向綁定。且LiveData在數(shù)據(jù)對(duì)于組件生命周期的表現(xiàn)更加優(yōu)秀在跳,且兼容更多類(lèi)型的數(shù)據(jù)枪萄,是官方推薦的。翻閱官方文章猫妙,發(fā)現(xiàn)需要我們這樣寫(xiě)瓷翻。5.結(jié)論
MVVM模式的優(yōu)勢(shì)不言而喻,而且由官方直接提供庫(kù)割坠,學(xué)了之后真的逃不過(guò)真香齐帚,MVVM+DataBinding+LiveData框架很強(qiáng)勢(shì)。組件的生命周期被監(jiān)聽(tīng)彼哼,最大限度的避免內(nèi)存溢出甚至閃退童谒。目前還感受不到MVVM在A(yíng)ndroid上的表現(xiàn)相較于傳統(tǒng)框架的大缺點(diǎn)』Ω幔可能比較弱勢(shì)的地方就是出現(xiàn)Bug的時(shí)候比較難定位饥伊,你無(wú)法得知出現(xiàn)問(wèn)題的是View層還是Model層。