1靡馁、MVVM模式各部分的定義
1.1呢堰、MVVM模式分為3個部分:Model旨剥、View和ViewModel咧欣。
(1)Model :數(shù)據(jù)層,包含數(shù)據(jù)實體和對數(shù)據(jù)實體的操作轨帜。
(2)View : 界面層该押,對應(yīng)于Activity、XML阵谚、View蚕礼,負責(zé)數(shù)據(jù)顯示以及用戶交互。
(3)ViewModel : 關(guān)聯(lián)層梢什,將Model和View進行綁定奠蹬,Model或View更改時,實時刷新對方嗡午。
1.2囤躁、注意點
(1)View只做和UI相關(guān)的工作,不涉及任何業(yè)務(wù)邏輯荔睹、不涉操作數(shù)據(jù)狸演、不處理數(shù)據(jù)。UI和數(shù)據(jù)嚴格的分開僻他。
(2)ViewModel只做和業(yè)務(wù)邏輯相關(guān)的工作宵距,不涉任何和UI相關(guān)的操作、不持有控件引用吨拗,不更新UI满哪。
2、MVVM模式圖
3劝篷、MVVM的優(yōu)勢和劣勢
3.1哨鸭、MVVM的優(yōu)勢
(1)、使得M,V,VM的解耦更加徹底娇妓,在mvp模式中像鸡,p需要持有v的引用,才能去刷新ui哈恰;在mvvm模式中只估,View和Model使用databingding進行雙向綁定华望,一方改變會直接通知另外一方,使得viewmodel能專注于業(yè)務(wù)邏輯的處理仅乓,而不需要去關(guān)心ui刷新。(最大優(yōu)勢蓬戚,下面兩個可忽略夸楣。)
(2)、不需要findViewById也不需要butterknife子漩,不需要拿到具體的View去設(shè)置數(shù)據(jù)等豫喧,這些都可以用DataBinding完成。
(3)幢泼、不會像MVC一樣導(dǎo)致Activity中代碼量巨大紧显,也不會像MVP一樣出現(xiàn)大量的View接口(Presente與View是通過接口進行交互的)。項目結(jié)構(gòu)更加低耦合缕棵。
3.2孵班、MVVM的劣勢
MVVM的缺點數(shù)據(jù)綁定使得Bug很難被調(diào)試。你看到界面異常了招驴,有可能是你 View 的代碼有 Bug篙程,也可能是 Model 的代碼有問題。
4别厘、Databinding框架
4.1虱饿、Databinding和MVVM的關(guān)系
MVVM是一種架構(gòu)模式,DataBinding是一個實現(xiàn)數(shù)據(jù)和UI綁定的框架触趴,是實現(xiàn)MVVM模式的工具氮发。
4.2、Databinding常用方法
4.2.1冗懦、BindingAdapter注解設(shè)置自定義屬性
public class ImageHelper {
/**
* 1.加載圖片,無需手動調(diào)用此方法
* 2.使用@BindingAdapter注解設(shè)置自定義屬性的名稱爽冕,imageUrl就是屬性的名稱,
* 當(dāng)ImageView中使用imageUrl屬性時披蕉,會自動調(diào)用loadImage方法扇售,
*
* @param imageView ImageView
* @param url 圖片地址
*/
@BindingAdapter({"imageUrl", "placeHolder",“error"})
public static void loadImage(ImageView view, String url, Drawable holderDrawable, Drawable errorDrawable) {
Glide.with(imageView.getContext())
.load(url)
.placeholder(holderDrawable)
.error(errorDrawable)
.into(imageView);
}
}
使用@BindingAdapter注解設(shè)置自定義屬性的名稱,如上所示嚣艇,imageUrl就是屬性的名稱承冰,當(dāng)ImageView中使用imageUrl屬性時,會自動調(diào)用loadImage方法食零,參數(shù)imageView為當(dāng)前使用imageUrl屬性的ImageView困乒,參數(shù)url為圖片地址。
xml中使用自定義屬性
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="com.zx.databindingdemo.bean.UserBean" />
<variable
name="user"
type="UserBean" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:orientation="vertical">
<!-- 當(dāng)imageUrl屬性存在時贰谣,會自動調(diào)用ImageHelper的loadImage方法 -->
<ImageView
android:layout_width="120dp"
android:layout_height="120dp"
android:scaleType="centerCrop"
app:error="@{user.errorUrl}"
app:placeHolder="@{user.placeHolder}"
app:imageUrl="@{user.picUrl}" />
</LinearLayout>
</layout>
Activity中設(shè)置圖片的url
public class BasicActivity extends AppCompatActivity {
//用戶頭像
private static final String URL_USER_PIC = "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=4138850978,2612460506&fm=200&gp=0.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityBasicBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_basic);
UserBean userBean = new UserBean(URL_USER_PIC, "張三", 24);
binding.setUser(userBean);
}
}
4.2.1娜搂、DataBinding動態(tài)更新數(shù)據(jù)的2種方式
(1)迁霎、BaseObservable
這個類也實現(xiàn)了字段變動的通知,在變量的getter上使用 Bindable注解百宇,并通過notifyPropertyChanged通知更新即可考廉。
public class DoubleBindBean extends BaseObservable {
// 用 @Bindable 標(biāo)記過 getxxx() 方法會在 BR 中生成一個 entry。 當(dāng)數(shù)據(jù)發(fā)生變化時需要調(diào)用 notifyPropertyChanged(BR.content) 通知系統(tǒng) BR.content這個 entry 的數(shù)據(jù)已經(jīng)發(fā)生變化以更新UI携御。
private String content; //內(nèi)容
public DoubleBindBean(String content) {
this.content = content;
}
@Bindable
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
notifyPropertyChanged(BR.content); //通知系統(tǒng)數(shù)據(jù)源發(fā)生變化昌粤,刷新UI界面
}
}
(2)、ObservableFields
如果想要省時啄刹,或者數(shù)據(jù)類的字段很少的話涮坐,可以使用 ObservableField 以及它的派生 ObservableBoolean、 ObservableByte ObservableChar誓军、ObservableShort袱讹、ObservableInt、ObservableLong昵时、ObservableFloat捷雕、ObservableDouble、 ObservableParcelable 等壹甥。
public class DoubleBindBean2 {
//變量需要為public
public final ObservableField<String> username = new ObservableField<>();
}
Observable Collections
除了支持ObservableField,ObservableBoolean非区,ObservableInt等基礎(chǔ)變量類型以外,當(dāng)然也支持集合框架拉盹廷,比如:ObservableArrayMap,ObservableArrayList征绸。使用和普通的Map、List基本相同