国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

Data Binding 的使用之一:簡單的數(shù)據(jù)綁定

2019-11-09 17:34:37
字體:
供稿:網(wǎng)友

一、簡介

    Data Binding是google發(fā)布的用以實現(xiàn)數(shù)據(jù)和UI綁定的框架,使用此框架可方便的實現(xiàn)MVVM開發(fā)模式。借用阮一峰老師對MVVM模式的概括:“MVVM 模式將 PResenter 改名為 ViewModel,基本上與 MVP 模式完全一致。唯一的區(qū)別是,它采用雙向綁定(data-binding):View的變動,自動反映在 ViewModel,反之亦然。Angular 和 Ember 都采用這種模式。”

使用Data Binding的優(yōu)點: 1. 避免了反復(fù)使用findViewById函數(shù)查找view,直接將view作為ViewDataBinding的成員變量。 2. 數(shù)據(jù)采用雙向綁定,借助android.databinding.BaSEObservable類,實現(xiàn)數(shù)據(jù)與視圖兩者的同步問題 3. 提供了多種表達式,可在xml布局文件中直接使用表達式完成數(shù)據(jù)處理 4. 為view提供多種callback,并提供lambda表達式功能,實現(xiàn)view的事件響應(yīng)

二、使用步驟

0.開發(fā)環(huán)境

    IDE:Android Studio

1.在module的build.gradle文件中,打開dataBinding

android{ ... dataBinding{ enabled = true }}

由于build.gradle更改后,Android Studio會在右上角自動提示是否sync now,點擊sync now

2.Data Bindingviewmodel進行解耦,避免在controller中或者在presenter中進行view與數(shù)據(jù)的處理。使用時,在界面對應(yīng)的layout文件中,添加標簽

<layout> ...</layout>

使原來的布局放置在兩個layout標簽中,即layout標簽為根標簽。注意layout為小寫。并將命名空間xmlns移到layout標簽下,即:

<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">或者 <layout xmlns:android="http://schemas.android.com/apk/res/android">

3.當添加完layout標簽后,Android Studio就會自動根據(jù)layout布局文件的名稱,生成對應(yīng)的java文件。 如,在activity_main.xml文件中添加layout根標簽后,會生成ActivityMainBinding.java,此類繼承自android.databinding.ViewDataBinding

由此可見,動態(tài)生成的ViewDataBinding類的命名規(guī)則是: 根據(jù)相應(yīng)的xml文件名稱,去掉下劃線,采用駝峰法,首字母大寫,最后添加Binding后綴,activity_main.xml對應(yīng)的ViewDataBinding類為ActivityMainBinding.java

4.在java文件中使用Data Binding時,去掉之前的context.setContentView,采用DataBindingUtil的函數(shù):

public static <T extends ViewDataBinding> T setContentView(Activity activity, int layoutId)

針對此例,在activityonCreate函數(shù)中使用如下代碼替換setContentView(R.layout.activity_main);

ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

binding對象根據(jù)對應(yīng)的layout文件中的內(nèi)容,實時動態(tài)的改變。如當為某個view添加id后,binding對象會自動根據(jù)新添加的id生成對應(yīng)的成員變量,此例中,我為一個TextView添加了android:id="@+id/title_text_view"binding對象中自動添加了titleTextView成員變量,這樣也就省去了findViewById的工作。同時我們可以看到,binding對象的命名規(guī)則是將布局文件中id的命名去掉下劃線,轉(zhuǎn)換為駝峰命名。如果文件中id的命名中沒有下劃線,則不會進行改變。

此時文件為:

package cn.carbs.android.testdatabinding;import android.databinding.DataBindingUtil;import android.databinding.ViewDataBinding;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import cn.carbs.android.testdatabinding.databinding.ActivityMainBinding;public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); binding.titleTextView.setText("hello data binding"); }}

MainActivity對應(yīng)的布局文件為:

<?xml version="1.0" encoding="utf-8"?><layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <RelativeLayout android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="cn.carbs.android.testdatabinding.MainActivity"> <TextView android:id="@+id/title_text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> </RelativeLayout></layout>

運行后,activity中的TextView顯示"hello data binding"

到此為止我們采用了在java代碼中使用binding.viewName.setXxx()的方式對view進行數(shù)據(jù)填充綁定。 下面使用另一種方式:在layout文件中添加data標簽進行數(shù)據(jù)綁定:

5.接著上面的步驟,在布局文件中,layout標簽下添加data標簽,并將data標簽做為layout標簽中的首個子標簽

<data> <variable name="aStudent" type="cn.carbs.android.testdatabinding.Student"/> </data>

name是變量的名稱,type是變量的類型,相當于cn.carbs.android.testdatabinding.Student aStudent;語句。(Student是一個java bean

在相應(yīng)的View中采用如下方式綁定數(shù)據(jù):

<TextView android:id="@+id/title_text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{aStudent.name}" />

在對應(yīng)的java文件中,相應(yīng)的ViewDataBinding對象就會根據(jù)變量名稱(data標簽中variable標簽下的name指定的變量名稱),生成set方法,此例中,可通過如下方式,在java類中綁定數(shù)據(jù)

Student s = new Student(); s.name = "Rick"; ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); binding.setAStudent(s);

即java類中負責設(shè)置beanxml布局文件中,負責將bean的信息分別設(shè)置到對應(yīng)的view上。 另外,android:text中的文字可以添加表達式,如下所示:

android:text='@{String.valueOf(1) + "_prefix_" + aStudent.name}'

可進行字符串連接,String的轉(zhuǎn)換等。如果需要使用到雙引號,即添加指定的字符串,那么將外層的雙引號改為單引號即可

6.在xml布局文件中綁定事件: android:onClick android:onLongClick android:onTextChanged等,其中onClickAndroid中本身帶有的屬性,而android:onLongClick android:onTextChanged則是Data Binding添加的。 首先在聲明響應(yīng)onClick等事件的類,如:

public class Presenter{ public void onClick(View v){ //do something... } }

其次在xml文件中,添加此類對應(yīng)的對象

<variable name="aPresenter" type="cn.carbs.android.testdatabinding.MainActivity.Presenter" />

并在TextView中添加對應(yīng)的onclick說明

android:onClick="@{aPresenter.onClick}"

三、原理說明

注意到,在編譯運行后,在app/build/generated/source/apt/debug/your_package_name/databinding文件夾中找到ActivityMainBinding.java文件,如下所示:

package cn.carbs.android.testdatabinding.databinding;import cn.carbs.android.testdatabinding.R;import cn.carbs.android.testdatabinding.BR;import android.view.View;public class ActivityMainBinding extends android.databinding.ViewDataBinding { private static final android.databinding.ViewDataBinding.IncludedLayouts sIncludes; private static final android.util.SparseIntArray sViewsWithIds; static { sIncludes = null; sViewsWithIds = new android.util.SparseIntArray(); sViewsWithIds.put(R.id.title_text_view, 1); } // views public final android.widget.RelativeLayout activityMain; public final android.widget.TextView titleTextView; // variables // values // listeners // Inverse Binding Event Handlers public ActivityMainBinding(android.databinding.DataBindingComponent bindingComponent, View root) { super(bindingComponent, root, 0); final Object[] bindings = mapBindings(bindingComponent, root, 2, sIncludes, sViewsWithIds); this.activityMain = (android.widget.RelativeLayout) bindings[0]; this.activityMain.setTag(null); this.titleTextView = (android.widget.TextView) bindings[1]; setRootTag(root); // listeners invalidateAll(); } @Override public void invalidateAll() { synchronized(this) { mDirtyFlags = 0x1L; } requestRebind(); } @Override public boolean haspendingBindings() { synchronized(this) { if (mDirtyFlags != 0) { return true; } } return false; } public boolean setVariable(int variableId, Object variable) { switch(variableId) { } return false; } @Override protected boolean onFieldChange(int localFieldId, Object object, int fieldId) { switch (localFieldId) { } return false; } @Override protected void executeBindings() { long dirtyFlags = 0; synchronized(this) { dirtyFlags = mDirtyFlags; mDirtyFlags = 0; } // batch finished } // Listener Stub Implementations // callback impls // dirty flag private long mDirtyFlags = 0xffffffffffffffffL; public static ActivityMainBinding inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot) { return inflate(inflater, root, attachToRoot, android.databinding.DataBindingUtil.getDefaultComponent()); } public static ActivityMainBinding inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot, android.databinding.DataBindingComponent bindingComponent) { return android.databinding.DataBindingUtil.<ActivityMainBinding>inflate(inflater, cn.carbs.android.testdatabinding.R.layout.activity_main, root, attachToRoot, bindingComponent); } public static ActivityMainBinding inflate(android.view.LayoutInflater inflater) { return inflate(inflater, android.databinding.DataBindingUtil.getDefaultComponent()); } public static ActivityMainBinding inflate(android.view.LayoutInflater inflater, android.databinding.DataBindingComponent bindingComponent) { return bind(inflater.inflate(cn.carbs.android.testdatabinding.R.layout.activity_main, null, false), bindingComponent); } public static ActivityMainBinding bind(android.view.View view) { return bind(view, android.databinding.DataBindingUtil.getDefaultComponent()); } public static ActivityMainBinding bind(android.view.View view, android.databinding.DataBindingComponent bindingComponent) { if (!"layout/activity_main_0".equals(view.getTag())) { throw new RuntimeException("view tag isn't correct on view:" + view.getTag()); } return new ActivityMainBinding(bindingComponent, view); } /* flag mapping flag 0 (0x1L): null flag mapping end*/ //end}

Data Binding在java編譯之前,首先會使用apt技術(shù),解析相關(guān)的xml等文件,并生成類文件,因此Data Binding使用的并非反射機制,這樣也就避免了使用反射造成的性能損耗。

四、注意事項

1.類似于ButterKnifeGreenDao3.x等第三方擴展庫,Data Binding會在運行時,根據(jù)布局文件通過一定的規(guī)則自動生成java文件,如果發(fā)現(xiàn)相應(yīng)的類沒有自動生成(Android Studio中會報錯,找不到響應(yīng)的類文件),可以采用clean或者rebuild的方式,讓AndroidStudio主動生成代碼。

參考:http://www.imooc.com/learn/719


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 平江县| 托克逊县| 农安县| 古蔺县| 庆元县| 墨脱县| 元谋县| 纳雍县| 宣城市| 水城县| 巴南区| 裕民县| 洛扎县| 沙坪坝区| 济源市| 杭州市| 东海县| 江陵县| 宝兴县| 阿荣旗| 刚察县| 洪洞县| 巴南区| 三门县| 罗平县| 工布江达县| 遵化市| 东莞市| 石渠县| 北京市| 台南市| 屏山县| 鲁山县| 岐山县| 靖边县| 济宁市| 尉氏县| 施秉县| 古丈县| 德江县| 唐河县|