studio對mvvm支持的也在不停的更新,但是還是有些問題沒有解決,比如說:
xml中加載圖片編譯時會爆出警告,xml中設置數據有幾種情況沒有提示,編譯時xml中出現錯誤並不會定位到錯誤的位置,等一些問題。
我相信這些問題很快會解決,現如今看mvvm還是很不錯的。
我接觸和開始使用mvvm是半年多前,當時真的只是爲了省略findViewById(哈哈),經過這幾個月的項目,慢慢才認識到mvvm的好處。
也踩了不少的坑,下面就記錄一下mvvm在xml中綁定數據的幾種處理方式。
首先我新建了一個工程在build.gradle中加入:
dataBinding{
enabled = true
}
然後將mainactivity的xml佈局修改一下,即在原來最外層的viewgroup外面在套一層<layout></layout>標籤,現在佈局是這個樣子的:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.xian.ge.myapplication.MainActivity">
</LinearLayout>
</layout>
這樣回到activity中,修改原來的setContentView,變成下面這樣:
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding activityMainBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
}
}
解釋幾句:
上面代碼中ActivityMainBinding這個對象是系統幫我們生成的。
例子:如果你的xml名字叫activity_first.xml的話,在你xml包上layout標籤的時候就會生成名字叫ActivityFirstBinding的對象。
如果你在activity中找不到的話,那就試着rebuild一下,重新編譯一次後就會找到。
下面最後一項準備工作,建一個實體類,這裏我就寫個簡單的用戶表,包括了名字,年齡,還有一個布爾的值用來控制是否顯示:
/**
* 用戶信息表
* Created by ge on 2017/5/7.
*/
public class UserEntity {
private String userName;
private int userAge;
private boolean isShow;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getUserAge() {
return userAge;
}
public void setUserAge(int userAge) {
this.userAge = userAge;
}
public boolean isShow() {
return isShow;
}
public void setShow(boolean show) {
isShow = show;
}
}
哦還有一個,我在xml中寫幾個view,方便下面演示:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.xian.ge.myapplication.MainActivity">
<TextView
android:id="@+id/tv_user_name"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_user_age"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/iv_user_head"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/btn_show"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="年齡段"/>
</LinearLayout>
</layout>
好了準備工作做完了。大家可以看到上面幾個控件我都起好了id。
下面就直接演示mvvm最基本的功能。。。省去了findViewById。
在activity中不用像以前一樣先去找到view在進行設置直接用剛纔實例化的binding對象就能找到:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
activityMainBinding.tvUserName.setText("葛大寶");
activityMainBinding.tvUserAge.setText("24歲");
activityMainBinding.btnShow.setText("青少年");
}
是不是很簡單。
實際項目中的數據一般都是我們請求拿到之後然後再設置,下面就看看在activity中設置數據變成了什麼樣子:
1.首先在xml中加入<data>標籤:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="userInfo"
type="com.xian.ge.myapplication.UserEntity"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.xian.ge.myapplication.MainActivity">
<!-- 節省地方省略其中控件,文章上面有 -->
</LinearLayout>
</layout>
這樣就直接在activity中設置數據了,如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
// 模擬拿到數據
UserEntity userEntity = new UserEntity();
userEntity.setUserName("葛大寶1");
userEntity.setShow(false);
userEntity.setUserAge(24);
// 設置到xml中顯示
activityMainBinding.setUserInfo(userEntity);
}
設置了之後我們就要回到xml中進入今天正題:
1.首先顯示名字:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{userInfo.userName}"/>
這是最簡單的直接@符號加{},中間用上面引入的數據對象設置即可。
2.控制button的顯示或隱藏:
因爲涉及到View的使用,所以要在data中引入View:
<data>
<import type="android.view.View"/>
<variable
name="userInfo"
type="com.xian.ge.myapplication.UserEntity"/>
</data>
這時候就可以直接使用了:
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="年齡段"
android:visibility="@{userInfo.show ? View.GONE : View.VISIBLE}"/>
大家看到這是用布爾類型來判斷,但是實際項目中不可能全是這麼簡單的判斷條件,可能需要通過一個int類型或者string類型來判斷,
那麼這時候就涉及到了引入外部工具類來幫助我們處理這個數據。
加入現在我們的判斷規則是,根據年齡來控制按鈕的顯隱性,年齡大於五十歲的隱藏,小於五十歲的顯示,
那麼首先我新建一個工具類:
/**
* 工具類
* Created by ge on 2017/5/7.
*/
public class DataUtils {
public static boolean isShow(int age){
return age < 50;
}
}
在xml中引入工具類:
<data>
<import type="android.view.View"/>
<import type="com.xian.ge.myapplication.DataUtils" alias="dataUtils"/>
<variable
name="userInfo"
type="com.xian.ge.myapplication.UserEntity"/>
</data>
大家看到我給工具類設置了一個別名,下面view中使用別名即可:
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="年齡段"
android:visibility="@{dataUtils.isShow(userInfo.userAge) ? View.GONE : View.VISIBLE}"/>
3.基礎類型引用
換一個場景,現在我的一個textView要顯示年齡,但是年齡是int類型,這時候根在class中沒啥區別:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{String.valueOf(userIfo.userAge)}"/>
像string,int, float等是不需要像上面使用View一樣在data中import進來的。
4.圖片的設置
新建圖片加載工具類:
/**
* 圖片加載
* Created by ge on 2017/5/5.
*/
public class ImageLoadViewModel {
@BindingAdapter({"bind:testState"})
public static void loadChildStateImg(ImageView view, String path){
Glide.with(view.getContext()).load(path)
.placeholder(path)
.into(view);
}
}
在xml中使用:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:testState="@{"圖片路徑"}"/>
參數傳的string,是圖片的路徑。
實際項目中也可能給你的不是個路徑,而是根據類型加載不同的圖片,也可能是本地圖片,那麼下面看下。
加載圖片的工具方法換成:
@BindingAdapter({"bind:testState"})
public static void loadChildStateImg(ImageView view, int type){
if (type == 1){
Glide.with(view.getContext()).load(path)
.placeholder(path)
.into(view);
}else {
Glide.with(view.getContext()).load(path)
.placeholder(path)
.into(view);
}
}
加載圖片按照上述寫法,編譯的時候會爆一個警告,不要理他。
先記錄到這,只寫了一些基本的用法,mvvm還有很多牛逼的地方,慢慢來。
如果你項目已經寫好了,想試試也沒關係,從最簡單的findViewById開始。