一,前言
百度上搜索了一堆,幾乎全是kotlin語言寫的,雖說看的懂,但是畢竟沒有在項目中實際用過此語言,還是比較吃力的,索性自個對照官方文檔慢慢琢磨.誰知道官網竟然沒有Java的實例,都是kotlin的,這可把我急壞了.!
AndroidStudio版本:3.6.3
SDK:29
二,使用
1,在build.gradle文件中添加, 切記 不可添加成了viewBinding
android {
...
dataBinding {
enabled = true
}
}
如果添加了viewbinding,那就會報如下錯誤.找不到 DataBindingUtil
2,佈局的使用及寫法。
根佈局代碼:
<layout>
<data>
<!--String-->
<variable
name="name"
type="String" />
</data>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
</LinearLayout>
</layout>
<layout>:只有layout包圍了系統纔會認識
<Data>:所有的變量,數據在此地聲明
<variable>:聲明變量方法
①,name:變量名字
②,type:變量類型
使用這個變量:
android:text="@{name}"
3,佈局中使用。
當你開啓了enabled = true,並且佈局根使用了layout包圍,那麼系統就會自動生成相對的類綁定
ActicityMainBindding 就是自動生成的。
①Activity 引用佈局 方式 binding = DataBindingUtil.setContentView(this, R.layout.activity_main) ;
public class MainActivity extends AppCompatActivity {
ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setName("劉備");
}
}
②如果您要在 Fragment、ListView 或 RecyclerView 適配器中使用數據綁定項,您可能更願意使用綁定類或 DataBindingUtil 類的 inflate() 方法,如以下代碼示例所示:
ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
// or
ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);
public class OneFragment extends androidx.fragment.app.Fragment {
FragmentOneBinding binding;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_one, container, false);
binding.setStr("我是Fragment");
return binding.getRoot();
}
}
4,佈局中設置變量的值
如果你在佈局文件中聲明瞭變量,那麼binding不會自動生成get set方法。只有你在view中使用到了這個變量纔會自動生成get,set方法
binding.setName("劉備");
那麼開始運行把:如圖
三,導入包,對象及常見運算符的使用
①導入方式
記住導入包,與之前在class中寫法一樣,無非換了一個地方。
2,接下來我們繼續往下走,測試每一個功能
①,給劉備增加一個年齡
<variable
name="age"
type="int" />
<TextView
...
android:text="@{age}"
>
艾瑪,怎麼會報錯:NotFoundException:String resource ID #0xa28,
找不到異常,找不到ID 是#0xa28的資源?
啥意思呢?我沒有定義字符串啊。
原來是這樣,我們TextView中的Text要接收的是String 類型 我們卻傳了一個int類型 !類型不匹配所以找不到。
解決方式:強制轉換(這個地方很容易忽略哈)
android:text="@{String.valueOf(age)}"
吶,出來了。
②:顯示隱藏View.根據true,false決定是否顯示隱藏
記得要導入上面說的包,
<import type="android.view.View"/>
<ImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:scaleType="fitXY"
android:src="@drawable/ic_lb"
android:visibility="@{isShow==true?View.VISIBLE:View.GONE}"
>
然後傳值:false就會隱藏了
binding.setIsShow(true);
掛在牆上的劉備出來了
③ Null 合併運算符其實就跟三元運算符一樣
binding.setStr1(null);
binding.setStr2("張飛");
//第一種寫法
android:text="@{str1??str2}"
//第二種
android:text="@{str1==null ? str1:str2}"
④圖片的引入
<variable name="image" type="Drawable"/>
Drawable drawable= getResources().getDrawable(R.drawable.ic_aa);
binding.setImage(drawable);
<ImageView
android:layout_width="50dp"
android:src="@{image}"
android:layout_height="50dp">
效果圖
四,對象,集合,數組的使用
常見的類型
<data>
<import type="android.util.SparseArray"/>
<import type="java.util.Map"/>
<import type="java.util.List"/>
<variable name="list" type="List<String>"/>
<variable name="sparse" type="SparseArray<String>"/>
<variable name="map" type="Map<String, String>"/>
<variable name="index" type="int"/>
<variable name="key" type="String"/>
</data>
①對象的使用
<variable
name="user"
type="com.cwj.databindingexample.User" />
...
android:text="@{user.name}"
...
binding.setUser(new User("諸葛亮"));
②數組的使用
<variable
name="arrays"
type="String[]" />
<variable
name="index"
type="int" />
③List集合的使用
請注意,
list[index]等於list.get(index),執行結果一樣。
<import type="java.util.List" />
<variable
name="index"
type="int" />
/>
①第一種
沒有指定後面的泛型
<variable
name="list"
type="List" />
需要這樣寫,不然默認是Object類型
android:text="@{String.valueOf(list[index])}"
②第二種
<variable
name="list"
type="List<String>//
/>
這裏不用強轉
android:text="@{list[index]}"
Activity 賦值
String arrays []={"呂布","趙子龍","馬超"};
ArrayList<String> list=new ArrayList();
list.add("許褚");
list.add("張遼");
list.add("張郃");
binding.setArrays(arrays);
binding.setList(list);
//下標
binding.setIndex(1);
結果如圖:
④Map 使用
<import type="java.util.Map" />
<variable
name="key"
type="String" />
<variable
name="map"
type="Map<String, String>" />
android:text="@{map.get(key)}"
android:text="@{map[key]}"
Map<String ,String > map= new TreeMap<>();
map.put("一","丈八蛇矛");
map.put("二","偃月刀");
map.put("三","青釭劍");
binding.setMap(map);
binding.setKey("二");
注意:官網說的這種寫法,我試了一下出不來
android:text="@{map.key}" 無效
五,資源的引用
① 使用
像下面這種寫法我之前有種疑問,就是不用@{}也可以用啊,爲啥多此一舉?
android:padding="@{@dimen/largePadding}"
②注意,關於多此一舉,主要用於改變UI的時候,比如大小字體,邊距等。
我定義了兩個尺寸
<resources>
<dimen name="largePadding">20dp</dimen>
<dimen name="smallPadding">2dp</dimen>
</resources>
<Button
...
android:padding="@{@dimen/largePadding}"
android:text="資源引用"></Button>
<Button
...
android:paddingLeft="@{number1==1 ? @dimen/largePadding : @dimen/smallPadding}"
android:text="資源引用大"></Button>
<Button
...
android:padding="@{number1==2 ? @dimen/largePadding : @dimen/smallPadding}"
android:text="資源引用小"></Button>
bind.setNumber1=1;
結果:可以看出由於,表達式的不同,結果選擇的也不一樣。
某些資源需要顯式類型
六,事件監聽
注意:1)如果您監聽的事件返回類型不是 void 的值,則您的表達式也必須返回相同類型的值。例如,如果要監聽長按事件,表達式應返回一個布爾值。
2)在你的方法中,會發現參數中有一個默認值的View view值 這是啥意思呢,
個人分析:有兩種寫法,第一種寫法是第二種寫法的簡寫,那麼這個theView是啥意思呢?其實就代表着當前view(Button) 然後隨便起個名字。前後對應。讓系統知道你在要在這個view上調用這個方法
① 點擊事件
1,第一種寫法
android:onClick="@{handlers::onClickToast}"
2,第二種寫法
android:onClick="@{(theView)->handlers.onClickToast(theView)}"
<variable
name="handlers"
type="com.cwj.databindingexample.MyHandlers" />
public class MyHandlers {
Context context;
public MyHandlers(Context context) {
this.context = context;
}
//這個方法的View要有
public void onClickToast(View view){
Toast.makeText(context, "你點擊了我!", Toast.LENGTH_SHORT).show();
}
}
binding.setHandlers(new MyHandlers(this));
②長按事件
第一種
android:onLongClick="@{handlers::onLongClick}"
第二種:
android:onLongClick="@{(a)->handlers.onLongClick(a)}"
public class MyHandlers {
Context context;
public MyHandlers(Context context) {
this.context = context;
}
public void onClickToast(View view){
Toast.makeText(context, "你點擊了我!", Toast.LENGTH_SHORT).show();
}
public boolean onLongClick(View view){
Toast.makeText(context, "你長按了了我!", Toast.LENGTH_SHORT).show();
return true;
}
}
這會發現,onClick方法和onLongCilck方法的寫法不一樣, 分析:看源碼返回值注意1)
public interface OnClickListener {
void onClick(View var1);
}
public interface OnLongClickListener {
boolean onLongClick(View var1);
}
③ 帶有參數的方法
這裏的參數我直接引用的上面的集合中的值。
android:onClick="@{(theView)->handlers.onClickToast(theView,list.get(index))}"
public void onClickToast(View view,String name){
Toast.makeText(context, "你點擊了 "+name, Toast.LENGTH_SHORT).show();
}
七,結尾
參考資料 官網
不足或者理解有偏差的地方,請指導。
持續更新。。。
源碼下載