<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                這篇博客是Data Binding Guide官網文檔翻譯的下篇,如果沒看過前半部分翻譯的可以先看[Data Binding Guide——google官方文檔翻譯(上)](http://blog.csdn.net/u014486880/article/details/50508133) ### 一,數據對象 任何不含業務邏輯的java簡單對象(POJO)可用于數據綁定,但修改POJO不能使UI更新。而通過數據綁定可以使數據對象感知到數據的變化。有三種不同的感知數據改變的機制,可見對象,可見字段,和可見集合。 當一個可見數據對象綁定到用戶界面和數據對象變化的屬性時,用戶界面將自動更新。 ### 可見對象 一個實現可見接口的類,允許把監聽器和對象綁定,以便監聽該對象的所有屬性的變化。 可見接口有添加和刪除偵聽器的機制,但數據改變的通知機制取決于開發者。為了使開發更簡潔,創建一個基類(BaseObservable)來實現監聽器注冊機制。當屬性改變時,數據實現類仍負責告知機制,其中getter方法加@Bindable注釋,并在setter方法中告知屬性的變化。 ~~~ private static class User extends BaseObservable { private String firstName; private String lastName; @Bindable public String getFirstName() { return this.firstName; } @Bindable public String getLastName() { return this.lastName; } public void setFirstName(String firstName) { this.firstName = firstName; notifyPropertyChanged(BR.firstName); } public void setLastName(String lastName) { this.lastName = lastName; notifyPropertyChanged(BR.lastName); } } ~~~ 在編譯過程中,綁定注釋在BR類文件中生成一個條目,然后在模塊包中生成BR類文件。如果數據類的基類不可改變,可以使用方便PropertyChangeRegistry有效地存儲和通知偵聽器的方式來實現可見接口。 ### ?可見字段 創建可見類的過程中,開發人員想節省時間或有很多屬性時可以使用可見字段,例如一些常用的可見類型字段:[ObservableBoolean](http://developer.android.com/reference/android/databinding/ObservableBoolean.html),?[ObservableByte](http://developer.android.com/reference/android/databinding/ObservableByte.html),?[ObservableChar](http://developer.android.com/reference/android/databinding/ObservableChar.html),[ObservableShort](http://developer.android.com/reference/android/databinding/ObservableShort.html),?[ObservableInt](http://developer.android.com/reference/android/databinding/ObservableInt.html),?[ObservableLong](http://developer.android.com/reference/android/databinding/ObservableLong.html),?[ObservableFloat](http://developer.android.com/reference/android/databinding/ObservableFloat.html),?[ObservableDouble](http://developer.android.com/reference/android/databinding/ObservableDouble.html),?and[ObservableParcelable](http://developer.android.com/reference/android/databinding/ObservableParcelable.html)。 可見字段是有獨立字段的可見對象。原始版本在訪問操作中避免裝箱和拆箱操作。為方便使用,在數據類創建使用public?final修飾的字段。 ~~~ private static class User { ? ?public final ObservableField<String> firstName = ? ? ? ?new ObservableField<>(); ? ?public final ObservableField<String> lastName = ? ? ? ?new ObservableField<>(); ? ?public final ObservableInt age = new ObservableInt(); } ~~~ 通過setter和getter方法獲取值。 ~~~ user.firstName.set("Google"); int age = user.age.get(); ~~~ 可見集合 ?一些應用程序使用更多的動態結構來保存數據。可見集合支持鍵控存取方式訪問這些數據對象。當鍵是一個像字符串這樣的引用類型時,可使用ObservableArrayMap。 ~~~ ObservableArrayMap<String, Object> user = new ObservableArrayMap<>(); user.put("firstName", "Google"); user.put("lastName", "Inc."); user.put("age", 17); ~~~ 在布局中,可以通過引用String類型的鍵進行映射: ~~~ <data> <import type="android.databinding.ObservableMap"/> <variable name="user" type="ObservableMap<String, Object>"/> </data> … <TextView android:text='@{user["lastName"]}' android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:text='@{String.valueOf(1 + (Integer)user["age"])}' android:layout_width="wrap_content" android:layout_height="wrap_content"/> ~~~ 當鍵是整型時,可使用[ObservableArrayList](http://developer.android.com/reference/android/databinding/ObservableArrayList.html)。 ~~~ ObservableArrayList<Object> user = new ObservableArrayList<>(); user.add("Google"); user.add("Inc."); user.add(17); ~~~ 在布局中,可通過索引訪問列表。 ~~~ <data> <import type="android.databinding.ObservableList"/> <import type="com.example.my.app.Fields"/> <variable name="user" type="ObservableList<Object>"/> </data> … <TextView android:text='@{user[Fields.LAST_NAME]}' android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}' android:layout_width="wrap_content" android:layout_height="wrap_content"/> ~~~ ### 生成綁定 任何不含業務邏輯的java簡單對象(POJO)可用于數據綁定,但修改POJO不能使UI更新。而通過數據綁定可以使數據對象感知到數據的變化。有三種不同的感知數據改變的機制,可見對象,可見字段,和可見集合。 當一個可見數據對象綁定到用戶界面和數據對象變化的屬性時,用戶界面將自動更新。 生成綁定類鏈接在布局視圖的布局變量,正如前面所討論的,綁定的名稱和包可以自定義。生成的綁定類都繼承ViewDataBinding。 應該立即創建綁定,以確保布局中的表達式與視圖的綁定不干擾視圖層。有幾種綁定到布局的方法。最常見的是在綁定類調用靜態方法inflate。inflate解析視圖,并完成數據綁定。還有一個更簡單的版本,只需要在inflate方法中引入LayoutInflater或再加上ViewGroup: ~~~ MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater); MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater, viewGroup, false); ~~~ 如果布局inflate機制有變化,也可以使用分開綁定的機制。 ~~~ MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot); ~~~ 在無法預先知道是否綁定的情況下,可以使用[DataBindingUtil](http://developer.android.com/reference/android/databinding/DataBindingUtil.html)?類創建綁定: ~~~ ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId, parent, attachToParent); ViewDataBinding binding = DataBindingUtil.bindTo(viewRoot, layoutId); ~~~ ### 有ID的視圖 在布局中每個有ID的視圖將相應生成一個public?final字段的變量,綁定類只調用一次布局,并創建每個視圖。這種機制比調用findViewById方法更有效率。 ~~~ <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="user" type="com.example.User"/> </data> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.firstName}" android:id="@+id/firstName"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.lastName}" android:id="@+id/lastName"/> </LinearLayout> </layout> ~~~ 會生成帶有如下屬性的綁定類: ~~~ public final TextView firstName; public final TextView lastName; ~~~ ID可能沒有數據綁定那樣必要,但是仍有一些實例證明,從代碼訪問角度看仍然是必要的。 ### 二、變量 每個變量會給出存取方法: ~~~ <data> <import type="android.graphics.drawable.Drawable"/> <variable name="user" type="com.example.User"/> <variable name="image" type="Drawable"/> <variable name="note" type="String"/> </data> ~~~ 在綁定中生成setter和getter方法: ~~~ public abstract com.example.User getUser(); public abstract void setUser(com.example.User user); public abstract Drawable getImage(); public abstract void setImage(Drawable image); public abstract String getNote(); public abstract void setNote(String note); ~~~ ### ViewStubs viewstubs與普通視圖不同。他們開始是是一個不可視并且大小為0的視圖,可以延遲到運行時填充布局資源。設置為Visible或調用inflate()之后,就會填充布局資源,ViewStub便會被填充的視圖替代。 由于ViewStub會在視圖層消失,為了正常的連接,對應的綁定對象也要隨之消失。由于視圖層是final類型的,ViewStubProxy對象替代ViewStub?后,開發者可以訪問?ViewStub,并且當?ViewStub?在視圖層中被加載時,開發者也可以訪問加載的視圖。 當解析其他布局時,新的布局中要建立綁定關系。因此,ViewStubProxy?對象要監聽[ViewStub的OnInflateListener](http://developer.android.com/reference/android/view/ViewStub.OnInflateListener.html)并建立綁定。開發者可以在ViewStubProxy?對象上建立一個OnInflateListener,綁定建立后,便可調用OnInflateListener。 ### 高級綁定 ### 動態變量 有時具體的綁定類會不被識別。例如,操作任意布局的[RecyclerView.Adapter](http://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html)必須在onBindViewHolder中指定綁定值,才可識別出對應的綁定類。 在這個例子中,RecyclerView綁定的所有布局都有一個item變量。BindingHolder?對象通過引用getBinding()?方法獲取?[ViewDataBinding](http://developer.android.com/reference/android/databinding/ViewDataBinding.html)?基類。 ~~~ public void onBindViewHolder(BindingHolder holder, int position) { final T item = mItems.get(position); holder.getBinding().setVariable(BR.item, item); holder.getBinding().executePendingBindings(); } ~~~ ### 立即綁定 當變量變化時,綁定在下一幀到來前也要隨之改變。然而,當綁定需要立即執行時,可以調用強制執行方法[executePendingBindings()](#)。 ### 后臺線程 可以在后臺線程中改變數據模型,只要它不是集合。數據綁定將每個變量或字段保存到本地,以避免任何并發問題。 ### 屬性Setters 只要綁定值有變化,生成的綁定類就會在視圖中調用setter方法。數據綁定框架可以自定義要調用的方法來設置值。 ### 自動Setters 對一個屬性來說,數據綁定試圖查找setAttribute方法。這與屬性的命名空間沒有關系,只與屬性本身有關。 例如?TextView?的屬性?android:text?上的表達式,數據綁定將查找setText(String)?方法,如果表達式返回值為?int,則會調用?setText(int)方法。注意表達式要返回正確的類型,有必要則使用cast進行類型轉換。即使沒有給定的屬性,數據綁定也會執行。可以通過數據綁定調用setter方法創建屬性。例如,DrawerLayout沒有任何屬性,但有很多setter方法,可以調用setter方法自動創建屬性。 ~~~ <android.support.v4.widget.DrawerLayout android:layout_width="wrap_content" android:layout_height="wrap_content" app:scrimColor="@{@color/scrim}" app:drawerListener="@{fragment.drawerListener}"/> ~~~ ### 重命名Setters 對于屬性setter方法與名字不匹配的情況,可以通過[BindingMethods](http://developer.android.com/reference/android/databinding/BindingMethods.html)注釋關聯名字和方法。類中包含[BindingMethod](http://developer.android.com/reference/android/databinding/BindingMethod.html)注釋,其中可以重命名set方法。例如,android:tint?屬性與[setImageTintList(ColorStateList)](#)方法相關,而與setTint不對應。 ~~~ @BindingMethods({ @BindingMethod(type = "android.widget.ImageView", attribute = "android:tint", method = "setImageTintList"), }) ~~~ 開發者不需要重命名setter方法,安卓框架已經做好了這方面的工作。 ### 自定義?Setters 一些屬性需要自定義綁定邏輯,android:paddingLeft?屬性并沒有對應的setter方法,但是存在setPadding(left,?top,?right,?bottom)方法。通過?BindingAdapter?注釋來自定義屬性調用的靜態setter方法。android?系統已經創建了?BindingAdapter?函數,下面是?paddingLeft?屬性對應的函數: ~~~ @BindingAdapter("android:paddingLeft") public static void setPaddingLeft(View view, int padding) { view.setPadding(padding, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()); } ~~~ 綁定適配器對于其他自定義類型很有幫助。例如可以在其他線程中自定義加載圖片。如果綁定適配器有沖突,則開發者自定義的將會重寫系統默認的綁定適配方法。一個適配器還可以有多個參數: ~~~ @BindingAdapter({"bind:imageUrl", "bind:error"}) public static void loadImage(ImageView view, String url, Drawable error) { Picasso.with(view.getContext()).load(url).error(error).into(view); } <ImageView app:imageUrl=“@{venue.imageUrl}” app:error=“@{@drawable/venueError}”/> ~~~ 如果用于?ImageView?的?imageUrl和?error?參數都存在并且?imageUrl?是?string?類型、error?是?drawable?類型?則就會調用上面定義的適配器。 在匹配適配器的時候,?會忽略自定義的命名空間你也可以為?android?命名空間的屬性自定義適配器。 ~~~ @BindingAdapter("android:paddingLeft") public static void setPaddingLeft(View view, int oldPadding, int newPadding) { if (oldPadding != newPadding) { view.setPadding(newPadding, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()); } } ~~~ 只能使用一個抽象方法的接口或抽象類調用事件處理程序。 ~~~ @BindingAdapter("android:onLayoutChange") public static void setOnLayoutChangeListener(View view, View.OnLayoutChangeListener oldValue, View.OnLayoutChangeListener newValue) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { if (oldValue != null) { view.removeOnLayoutChangeListener(oldValue); } if (newValue != null) { view.addOnLayoutChangeListener(newValue); } } } ~~~ 當一個監聽器有多種方法時,必須要分割成多個監聽器。 例如,OnAttachStateChangeListener包含兩個方法,?onViewAttachedToWindow()?和onViewDetachedFromWindow(),必須創建兩個接口用于區分屬性和處理程序。 ~~~ @TargetApi(VERSION_CODES.HONEYCOMB_MR1) public interface OnViewDetachedFromWindow { void onViewDetachedFromWindow(View v); } @TargetApi(VERSION_CODES.HONEYCOMB_MR1) public interface OnViewAttachedToWindow { void onViewAttachedToWindow(View v); } ~~~ 一個監聽器的改變也會影響另外一個,所以必須有三個不同的綁定適配器,每個監聽器分別對應一個,兩個監聽器對應第三個綁定適配器。 ~~~ @BindingAdapter("android:onViewAttachedToWindow") public static void setListener(View view, OnViewAttachedToWindow attached) { setListener(view, null, attached); } @BindingAdapter("android:onViewDetachedFromWindow") public static void setListener(View view, OnViewDetachedFromWindow detached) { setListener(view, detached, null); } @BindingAdapter({"android:onViewDetachedFromWindow", "android:onViewAttachedToWindow"}) public static void setListener(View view, final OnViewDetachedFromWindow detach, final OnViewAttachedToWindow attach) { if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1) { final OnAttachStateChangeListener newListener; if (detach == null && attach == null) { newListener = null; } else { newListener = new OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View v) { if (attach != null) { attach.onViewAttachedToWindow(v); } } @Override public void onViewDetachedFromWindow(View v) { if (detach != null) { detach.onViewDetachedFromWindow(v); } } }; } final OnAttachStateChangeListener oldListener = ListenerUtil.trackListener(view, newListener, R.id.onAttachStateChangeListener); if (oldListener != null) { view.removeOnAttachStateChangeListener(oldListener); } if (newListener != null) { view.addOnAttachStateChangeListener(newListener); } } } ~~~ 上面的例子比正常的要稍微復雜,因為視圖對監聽器用添加和刪除方法替代set方法。 android.databinding.adapters.ListenerUtil類幫助跟蹤之前的監聽器,以便在綁定適配器中及時移除相應的監聽器。 通過用@TargetApi(VERSION_CODES.HONEYCOMB_MR1)注釋接口OnViewDetachedFromWindow?and?OnViewAttachedToWindow?。數據綁定代碼生成器知道只能在產生蜂窩MR1和新設備中運行時才會生成監聽器。 ### 轉換器(Converters) ### 對象轉換 當綁定表達式返回一個對象時候,將會自動調用?set?函數、重命名的函數、或者自定義的?setter?中的一個。表達式返回的對象將會轉換為該函數的參數類型。 使用?ObservableMaps?來保存數據會比較簡單。例如: ~~~ <TextView android:text='@{userMap["lastName"]}' android:layout_width="wrap_content" android:layout_height="wrap_content"/> ~~~ 這里的?userMap?返回的對象將制動轉換為?setText(CharSequence)?的參數。?如果參數不明確,則開發者需要強制轉換為需要的類型。 ### 自定義轉換規則 有時候參數應該可以自動轉換,例如 ~~~ <View android:background="@{isError ? @color/red : @color/white}" android:layout_width="wrap_content" android:layout_height="wrap_content"/> ~~~ 上面的背景需要一個?Drawable?對象,但是表達式的返回值為整數對象的顏色值。這種情況下,顏色值需要轉換為?ColorDrawable。?這種轉換通過一個靜態函數完成,該函數帶有一個?BindingConversion?注解。 ~~~ @BindingConversion public static ColorDrawable convertColorToDrawable(int color) { return new ColorDrawable(color); } ~~~ 需要注意的是,轉換是在?setter上完成的,所以不能把不同的類型混合使用: ~~~ <View android:background="@{isError ? @drawable/error : @color/white}" android:layout_width="wrap_content" android:layout_height="wrap_content"/> ~~~ ### 三、Android?Studio?支持數據綁定 Android?Studio支持數據綁定表達式的語法高亮顯示,并在編輯器中顯示任何表達式語言語法錯誤。 預覽窗格顯示數據綁定表達式的默認值。以下從布局XML文件的元素實例摘錄。 ~~~ <TextView android:layout_width="wrap_content" ? ?android:layout_height="wrap_content" ? ?android:text="@{user.firstName, default=PLACEHOLDER}"/> ~~~ 如果項目的設計階段需要顯示一個默認值,可以使用工具屬性而不是默認的表達式的值。 到此Data Binding官方文檔就翻譯完了。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看