<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>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 背景 略。 # 環境設置 要開始使用databinding,需要在module里面的build.gradle配置好相關的環境: 具體參照以下代碼: android { .... dataBinding { enabled = true } } 如果一個library module設置了databinding,那么app module也*必須* 在build.gradle加上以上代碼。 # 在布局文件中使用databinding ## 示例代碼 數據綁定布局文件和一般布局文件略有不同,它以`<layout>`的根標簽開始,后跟`<data>`標簽和*視圖根元素*,即一般的視圖布局。示例文件如下所示: <?xml version="1.0" encoding="utf-8"?> <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}"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{user.lastName}"/> </LinearLayout> </layout> 其中`<data>`標簽里面的`<variable>`標簽聲明好需要綁定的數據,后面還可以看到`<import>`等標簽的使用。 ## 綁定語法 * 數據綁定 綁定數據的表達式通過 `@{}` 語法寫入標簽的屬性里面,例如:`android:text="@{user.firstName}"`這句代碼就是把user.firstName設置到`android:text`屬性里面。 `@{}`里面的表達式,如果是對象引用,例如`user.firstName`,表達式求值的時候,會首先查找對象的getter方法,即`getFirstName()`方法。如果存在此方法,則以返回值作為表達式的值。如果不存在對應的getter,則會查找公開的字段,如果沒有相同命名的公開字段,編譯時就會報錯。 雙向綁定的語法是 `@={}` ,需要注意的是這是一項實驗性功能,尚未到正式版本。 * 事件處理 事件綁定語法和數據綁定差不多,都是通過 `@{}` 把方法的引用([Java8的語法](https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html))給到特定的屬性。 但相對于屬性,設置方法的語法還是需要留意一下: * 基本語法:把一個lambda表達式或者通過方法引用語法`::`設置方法到事件屬性里面,例如最常見的點擊事件 android:onClick="@{(v) -> presenter.onClick()}" 或者是: android:onClick="@{presenter::onClickView}" 使用`::`語法的時候,需要保證的是`pesenter.onClickView`方法擁有和對應的事件方法同樣的參數,即`onClickView`方法的定義必須是下面這樣: public T onClickView(View view){ ... } * 假如需要方法里面的參數,只要需要其中一個,都要把所有參數寫上: app:onTagClickListener="@{(view,tag,position) -> presenter.addListItem(position)}" * 假如不需要任何方法里面的參數,那么括號里面的參數列表可以省略: app:onTagClickListener="@{() -> presenter.onLoadMore()}" * 如果方法需要有返回值,那么你的表達式或者方法的返回類型一定要和屬性的返回類型一致,否則會編譯不通過。 ## 其他布局細節 ### Import導包 `<data>`標簽里面還支持import語法,具體的格式是下面這樣,跟java代碼里面差不多: <data> <import type="android.view.View"/> </data> 導包之后就可以使用它的一些靜態方法或者靜態變量,例如`View.GONE`等等,甚至可以導入`TextUtils`來判斷字符串非空。但由于可讀性和可維護性方面的問題,我們在項目中應該**禁止**xml中使用任何條件語句。 關于*import*更詳細的資料請查看[官方文檔](https://developer.android.com/topic/libraries/data-binding/index.html#imports) ### Variables變量 `variable`標簽會為每個聲明的變量賦初始值,如果是引用類型則初始值為null,int類型是0,等等。 xml中有一個隱藏的變量名`context`,它對應的值是布局根元素的`getContext`方法獲取的上下文對象。如果你的xml中顯式聲明`context`變量,那么這個變量會被你的聲明所覆蓋。 關于*variable*更詳細的資料請查看[官方文檔](https://developer.android.com/topic/libraries/data-binding/index.html#variables)。 ### 自定義生成的綁定類名 默認情況下,根據布局文件的名稱生成一個Binding類,以大寫字母開頭,刪除下劃線`_`并大寫后面的字母,然后后綴“Binding”。 該類將放置在模塊包下的數據綁定包中。 例如,布局文件contact_item.xml將生成ContactItemBinding。 如果模塊包是com.example.my.app,那么它將被放置在com.example.my.app.databinding中。 綁定類可以通過調整`<data>`元素的`class`屬性來重命名或放置在不同的包中。 例如: <data class="ContactItem"> ... </data> 以上設置會把xml生成的對應綁定類重命名為ContactItem,而不是XXXBinding。`class`屬性還可以設置相對或者完整包名,具體請查看[官方文檔](https://developer.android.com/topic/libraries/data-binding/index.html#custom_binding_class_names) ### Inclub標簽綁定 略。 [官方文檔](https://developer.android.com/topic/libraries/data-binding/index.html#includes)。 ### 布局中可以使用的表達語言 從可讀性和可維護性的角度觸發,我們項目中禁止布局文件中做任何邏輯和業務相關的表達式運算,綁定的字段一般就是最終的輸出。作為了解,可以查看一下[官方文檔](https://developer.android.com/topic/libraries/data-binding/index.html#expression_language)。 # 綁定的數據對象 從上面的介紹得知,我們可以把普通的java對象(POJO)或者java bean對象(BEAN)綁定到屬性里面,但是當這些對象的屬性發生變化的時候,頁面是不會隨之發送變化的。如果需要屬性變化馬上反應到視圖上,就要使用綁定庫提供的`Data Objects`。有以下三種實現方法提供: * 繼承BaseObservable,為需要實時變更的get方法加上`@Bindable`注解,編譯器會自動為該方法生成對應的id存放在BR里面(類似R文件)。對應的set方法需要調用`notifyPropertyChanged(id)`,例如: 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); } } * 使用ObservableField和他的同胞 ObservableBoolean, ObservableByte, ObservableChar, ObservableShort, ObservableInt, ObservableLong, ObservableFloat, ObservableDouble, and ObservableParcelable.使用它們來替代你的類中需要實時變化的字段類型,不需要額外設置get set方法,但修飾符需要是`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(); } * 使用Observable Collections,例如 ObservableArrayMap 和 ObservableArrayList。在xml中可以使用符號[]訪問。但直接使用集合來綁定數據,還是會破壞可讀性。在類中使用的話和ObservableField無異。所以有需要了解的請查看[官方文檔](https://developer.android.com/topic/libraries/data-binding/index.html#observable_collections)。 # 生成的綁定類淺析 前面已經介紹過,編譯器會為每一個使用數據綁定的xml生成一個繼承`android.databinding.ViewDataBinding`的綁定類。綁定類處理好所有該布局文件的屬性綁定和事件處理,并且提供對外的設置綁定對象的方法。這個類可以重命名,可以自定義包名等等,這些在之前已經描述過。 ## 創建綁定 在布局被`inflate`之后應該盡快綁定,避免對View的操作造成綁定失敗。綁定的方法一般有以下幾種: * 用生成的綁定類`inflate`,會同時執行好布局的`inflate`和綁定,無須額外操作: MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater); MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater, viewGroup, false); * 如果布局是使用不同的機制來進行`inflate`的,可以使用綁定類的`bind`方法進行綁定: MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot); * 或者都可以直接用`DataBindingUtil.inflate`方法進行創建布局、生成綁定,相比具體的綁定類,只是多了參數,返回的類型是`<T extends ViewDataBinding>`: ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId, parent, attachToParent); * 在Activity中可以使用`DataBindingUtil.setContentView`方法類代替activity原有的`setContentView`方法: ActivityMain2Binding binding = DataBindingUtil.setContentView(activity.this, R.layout.activity_main2); ## 為帶id的元素生成引用 簡直就是**福音**!!!綁定類會為所有布局中帶id的元素生成引用,例如在xml中寫了一個TextView是id是`text`,綁定類里面就會生成一個`public final TextView text;`的引用,從此告別`findViewById`,我簡直都要哭了~生成的字段名的規則是首字母小寫,下劃線去除,下劃線后的首字母大寫。 ## 為變量生成代碼 綁定類會為定義在`<variable>`標簽的對象生成對應的`get` `set`方法,如果有涉及到事件處理,還會根據事件傳入方式生成一些監聽器或者一些事件回調類: // variables @Nullable private com.healthmall.library.app.databinding.DataBindingListItemInfoVM mItem; @Nullable private com.healthmall.library.app.databinding.ListPresenter mPresenter; @Nullable private final android.view.View.OnClickListener mCallback4; // values // listeners private OnClickListenerImpl mPresenterOnClickViewAndroidViewViewOnClickListener; ## ViewStub綁定 提供了ViewStubProxy來解決ViewStub的綁定問題,具體請看[ViewStubProxy文檔](https://developer.android.com/reference/android/databinding/ViewStubProxy.html)。 ## 高級特性 ### 動態綁定 編譯器會為xml的每個變量生成對應的id,綁定類會為每個變量生成對應的get、set方法,但有時候我們沒辦法確定具體的id和具體的對象,譬如我們在編寫adapter基類,假設我們有一個統一的id `BR.item` ,但所有列表對象都基本不一致。所以需要使用ViewDataBinding(綁定類的基類)提供的`setVariable(bindId, bindObject)`方法來進行動態綁定。 @Override public final void onBindViewHolder(BaseBindingViewHolder holder, int position) { // 綁定數據 holder.bind.setVariable(BR.item, list.get(position)); holder.bind.executePendingBindings(); } ### 綁定立即生效 當變量或可觀察到的變化時,綁定將被安排在下一幀之前改變。 然而,有時候,綁定必須立即執行。 要強制執行,請使用`executePendingBindings`方法。 ### 線程安全 只要不是集合,您可以在后臺線程中更改數據模型。 數據綁定將在評估時本地化每個變量/字段以避免任何并發問題。 # 屬性設置器 屬性設置器是編譯器連接代碼和布局的一套規則,它決定了綁定類如何生成。除了默認的規則以外,數據綁定框架還提供了自定義的方法,來幫助我們按照自己的規則去建立綁定。作為開發者而言,個人認為這是我們最應該熟悉的部分,沒有它上面的語法都不成立。 ## 屬性自動設置器 對于綁定的任意一個屬性(忽略namespace),它會根據自己的屬性名去尋找對應的setter方法,而不管對應控件中是否已經聲明相同名稱的屬性字段。例如TextView里面的`android:text`屬性,關聯的表達式會被設置到`setText()`方法里面。例如我們的圖片顯示控件ThumbnailDraweeView,雖然沒有一個名為`imageURI`的屬性,但有`setImageURI`方法,所以我們可以輕松的使用`imageURI`屬性去為控件設置要顯示的圖片: <com.gzdxjk.healthmall_android_library.widget.facebook.ThumbnailDraweeView android:id="@+id/image" android:layout_width="60dp" android:layout_height="60dp" android:layout_margin="15dp" app:imageURI="@{item.url}" /> 有了這個機制以后,我們可以為任何setter方法在xml中創造對應的屬性,而不需要預先在控件中定義,包括事件處理,這也是極大的增加了靈活性。例如: <com.gzdxjk.healthmall_android_library.widget.LoadingView android:id="@+id/loading" android:layout_width="match_parent" android:layout_height="match_parent" app:noDataMessage="@{flowlist.noDataMsg}" app:onRefreshListener="@{() -> presenter.onStart(loading, context, flowlist)}"> 以上示例里面可以看到,我們項目中的LoadingView并沒有`noDataMessage`這個屬性,也沒有`onRefreshListener`這個屬性,但通過自動設置器,相應的表達式還是正確的設置到了對應的方法里面。 ## 重命名設置器 有的屬性對應的setter方法會跟屬性名不一致,例如ImageView的`android:tint`屬性,它對應的方法是`setImageTintList`,而不是`setTint`。這時候可以使用`@BindingMethods`注解來重命名setter,它是一個類注解: @BindingMethods({ @BindingMethod(type = "android.widget.ImageView", attribute = "android:tint", method = "setImageTintList"), }) ## 自定義設置器 假如存在的屬性沒有對應的setter方法,那么可以編寫一個由`@BindingAdapter`注解的靜態方法來自定義該屬性的行為,例如`android:paddingLeft`屬性,并沒有一個`setPaddingLeft`方法讓自動設置器去設置它對應的表達式,這時候可以: @BindingAdapter("android:paddingLeft") public static void setPaddingLeft(View view, int padding) { view.setPadding(padding, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()); } 假如自動設置器提供的方法不滿足你的需求,你也可以使用自定義設置器去覆蓋系統提供的方法。 BindingAdapter還可以接收多個參數,對應到一個方法里面。例如我們的流式布局FlowLayout中的自定義設置器: @BindingAdapter({"bind:child_layout", "bind:items"}) public static void bindTextItem(FlowLayout flowLayout, int childLayoutId, List<String> itemList) { flowLayout.addTextTag(childLayoutId, itemList); } 當布局中的`child_layout`和`items`屬性同時存在(忽略namespace)并且它們的表達式返回類型和定義好的方法一致時,將會調用`bindTextItem`方法: <com.gzdxjk.healthmall_android_library.widget.FlowLayout android:id="@+id/flow_layout" android:layout_width="match_parent" android:layout_height="300dp" app:child_layout="@{@layout/layout_textview}" app:items="@{flowlist.list}" app:onTagClickListener="@{(view,tag,position) -> presenter.addListItem(position)}" /> BindingAdapter還允許其處理方法使用變化前的值,具體的格式應該是舊值在前,新值在后: @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()); } } 對于一個接口有多個方法的情況,必須為每個方法重寫一個接口,并且在自定義設置器中一一對應,由于情況比較特殊,具體實例請查看[官方文檔](https://developer.android.com/topic/libraries/data-binding/index.html#custom_setters)。 # 數據類型轉換 同樣,為了可讀性考慮,禁止在xml中使用數據類型轉換。
                  <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>

                              哎呀哎呀视频在线观看