欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android DataBinding的官方雙向綁定示例

 更新時間:2017年10月23日 17:22:50   作者:SoloHo  
本篇文章主要介紹了Android DataBinding的官方雙向綁定示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

在Android Studio 2.1 Preview 3之后,官方開始支持雙向綁定了。

可惜目前Google并沒有在Data Binding指南里面加入這個教程,并且在整個互聯(lián)網(wǎng)之中只有這篇文章介紹了如何使用反向綁定。

在閱讀一下文章之前,我假設(shè)你已經(jīng)知道如何正向綁定。

回顧一下Data Binding

在正向綁定中,我們在Layout里面的綁定表達式是這樣的:

<layout ...>
 <data>
  <variable type="com.example.myapp.User" name="user"/>
 </data>
 <RelativeLayout ...>
  <TextView android:text="@{user.name}" .../>
 </RelativeLayout>
</layout>

當user.name的數(shù)據(jù)改動時,我們的TextView都會同步改變文字。

雙向綁定

現(xiàn)在假設(shè)一種情況,當你更換成EditText時,如果你的用戶名User.name已經(jīng)綁定到EditText中,當用戶輸入文字的時候,你原來的user.name數(shù)據(jù)并沒有同步改動,因此我們需要修改成:

<layout ...>
 <data>
  <variable type="com.example.myapp.User" name="user"/>
 </data>
 <RelativeLayout ...>
  <EditText android:text="@={user.name}" .../>
 </RelativeLayout>
</layout>

看出微小的差別了嗎?對,就是"@{}"改成了"@={}",是不是很簡單?

隱式引用屬性

同樣你也可以在別的View上引用屬性:

<layout ...>
 <data>
  <import type="android.view.View"/>
 </data>
 <RelativeLayout ...>
  <CheckBox android:id="@+id/seeAds" .../>
  <ImageView android:visibility="@{seeAds.checked ? View.VISIBLE : View.GONE}" .../>
 </RelativeLayout>
</layout>

當CheckBox的狀態(tài)發(fā)生改變的時候,ImageView也會同時發(fā)生改變。在復雜情況下,這個特性沒什么卵用,因為邏輯部分我們是不建議寫在XML中。

如何開啟雙向綁定

開啟雙向綁定,需要在項目的build.gradle中設(shè)置:

classpath 'com.android.tools.build:gradle:2.1.0-alpha3'

同樣,你需要在你Module的build.gradle中設(shè)置:

android {
  ...
  dataBinding.enabled = true
}

貌似還有點問題

我們剛才的例子里面只顯示了系統(tǒng)自帶的應(yīng)用,那么如果是自定義控件,或者是我們更細顆粒度的Observable呢?等下就揭曉如何自定義自己的雙向綁定,我們來看看目前Android支持的控件:

  1. AbsListView android:selectedItemPosition
  2. CalendarView android:date
  3. CompoundButton android:checked
  4. DatePicker android:year, android:month, android:day
  5. NumberPicker android:value
  6. RadioGroup android:checkedButton
  7. RatingBar android:rating
  8. SeekBar android:progress
  9. TabHost android:currentTab (估計沒人用)
  10. TextView android:text
  11. TimePicker android:hour, android:minute

自定義雙向綁定

設(shè)想一下我們使用了下拉刷新SwipeRefreshLayout控件,這個時候我們希望在加載數(shù)據(jù)的時候能控制refreshing的狀態(tài),所以我們加入了ObservableBoolean的變量swipeRefreshViewRefreshing來正向綁定數(shù)據(jù),并且能夠在用戶手動下拉刷新的時候同步更新swipeRefreshViewRefreshing數(shù)據(jù):

// SwipeRefreshLayout.java

public class SwipeRefreshLayout extends View {
  private boolean isRefreshing;
  public void setRefreshing() {/* ... */}
  public boolean isRefreshing() {/* ... */}
  public void setOnRefreshListener(OnRefreshListener listener) {
    /* ... */
  }
  public interface OnRefreshListener {
    void onRefresh();
  }
}

接下來我們需要告訴框架,我們需要將SwipeRefreshLayout的isRefreshing的值反向綁定到swipeRefreshViewRefreshing

@InverseBindingMethods({
    @InverseBindingMethod(
        type = android.support.v4.widget.SwipeRefreshLayout.class,
        attribute = "refreshing",
        event = "refreshingAttrChanged",
        method = "isRefreshing")})

這是一種簡單的定義,其中event和method都不是必須的,因為系統(tǒng)會自動生成,寫出來是為了更好地了解如何綁定的,可以參考官方文檔InverseBindingMethod。

當然你也可以使用另外一種寫法,并且如果你的值并不是直接對應(yīng)Observable的值的時候,就可以在這里進行轉(zhuǎn)換:

@InverseBindingAdapter(attribute = "refreshing", event = "refreshingAttrChanged")
public static boolean isRefreshing(SwipeRefreshLayout view) {
  return view.isRefreshing();
}

上面的event同樣也不是必須的。以上的定義都是為了讓我們能夠在布局文件中使用"@={}"這個雙向綁定的特性。接下來你需要告訴框架如何處理refreshingAttrChanged事件,就像處理一般的監(jiān)聽事件一樣:

@BindingAdapter("refreshingAttrChanged")
public static void setOnRefreshListener(final SwipeRefreshLayout view,
  final InverseBindingListener refreshingAttrChanged) {

  if (refreshingAttrChanged == null) {
    view.setOnRefreshListener(null);
  } else {
    view.setOnRefreshListener(new OnRefreshListener() {
      @Override
      public void onRefresh() {
        colorChange.onChange();
      }
    });
  }
}

一般情況下,我們都需要設(shè)置正常的OnRefreshListener,所以我們可以合并寫成:

@BindingAdapter(value = {"onRefreshListener", "refreshingAttrChanged"}, requireAll = false)
public static void setOnRefreshListener(final SwipeRefreshLayout view,
  final OnRefreshListener listener,
  final InverseBindingListener refreshingAttrChanged) {

  OnRefreshListener newValue = new OnRefreshListener() {
    @Override
    public void onRefresh() {
      if (listener != null) {
        listener.onRefresh();
      }
      if (refreshingAttrChanged != null) {
        refreshingAttrChanged.onChange();
      }
    }
  };

  OnRefreshListener oldValue = ListenerUtil.trackListener(view, newValue, R.id.onRefreshListener);
  if (oldValue != null) {
    view.setOnRefreshListener(null);
  }
  view.setOnRefreshListener(newValue);
}

現(xiàn)在我們終于可以使用雙向綁定的技術(shù)啦。但是要注意,需要設(shè)置requireAll = false,否則系統(tǒng)將識別不了refreshingAttrChanged屬性,前文提到的文章例子里并沒有設(shè)置這個。

在ViewModel中,我們的數(shù)據(jù)是這樣的:

// MyViewModel.java

public final ObservableBoolean swipeRefreshViewRefreshing = new ObservableBoolean(false);

public void load() {
  swipeRefreshViewRefreshing.set(true);

  // 網(wǎng)絡(luò)請求
  ....

  swipeRefreshViewRefreshing.set(false);
}

public SwipeRefreshLayout.OnRefreshListener onRefreshListener() {
  return new SwipeRefreshLayout.OnRefreshListener() {
    @Override
    public void onRefresh() {
      // Do something you need
    }
  };
}

在布局文件中是這樣設(shè)置的:

<android.support.v4.widget.SwipeRefreshLayout
  android:id="@+id/swipe_refresh_view"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  app:onRefreshListener="@{viewModel.onRefreshListener}"
  app:refreshing="@={viewModel.swipeRefreshViewRefreshing}">

  ...
</android.support.v4.widget.SwipeRefreshLayout>

最后我們還有一個小問題,就是雙向綁定有可能會出現(xiàn)死循環(huán),因為當你通過Listener反向設(shè)置數(shù)據(jù)時,數(shù)據(jù)也會再次發(fā)送事件給View。所以我們需要在設(shè)置一下避免死循環(huán):

@BindingAdapter("refreshing")
public static void setRefreshing(SwipeRefreshLayout view, boolean refreshing) {
  if (refreshing != view.isRefreshing()) {
    view.setRefreshing(refreshing);
  }
}

這樣就沒問題啦。以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android客戶端實現(xiàn)注冊、登錄詳解(2)

    Android客戶端實現(xiàn)注冊、登錄詳解(2)

    這篇文章主要為大家詳細介紹了Android客戶端實現(xiàn)注冊、登錄代碼第二篇,App與服務(wù)器的交互實現(xiàn)登錄和自動登錄功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Android實現(xiàn)Service在前臺運行服務(wù)

    Android實現(xiàn)Service在前臺運行服務(wù)

    這篇文章主要為大家詳細介紹了Android中實現(xiàn)Service在前臺運行服務(wù),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Android數(shù)據(jù)加密之SHA安全散列算法

    Android數(shù)據(jù)加密之SHA安全散列算法

    這篇文章主要為大家詳細介紹了Android數(shù)據(jù)加密之SHA安全散列算法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Android LaunchMode四種啟動模式詳細介紹

    Android LaunchMode四種啟動模式詳細介紹

    這篇文章主要介紹了Android LaunchMode四種啟動模式詳細介紹的相關(guān)資料,這里對launchmode的使用方法進行了詳解及啟動模式的比較,需要的朋友可以參考下
    2016-12-12
  • Android?狀態(tài)管理之Lifecycle淺析

    Android?狀態(tài)管理之Lifecycle淺析

    這篇文章主要介紹了Android?狀態(tài)管理之Lifecycle淺析,Lifecycle主要用于Activity、Fragment這一類具有狀態(tài)的組件的狀態(tài)監(jiān)聽,更多相關(guān)資料介紹需要的小伙伴可以參考下面文章內(nèi)容
    2022-06-06
  • Android 實現(xiàn)ListView的點擊變色的實例

    Android 實現(xiàn)ListView的點擊變色的實例

    這篇文章主要介紹了Android 實現(xiàn)ListView的點擊變色的實例的相關(guān)資料,主要實現(xiàn)Android listveiw ItemClickListener寫入變色的功能,需要的朋友可以參考下
    2017-07-07
  • Android編程簡單實現(xiàn)ImageView點擊時背景圖修改的方法

    Android編程簡單實現(xiàn)ImageView點擊時背景圖修改的方法

    這篇文章主要介紹了Android編程簡單實現(xiàn)ImageView點擊時背景圖修改的方法,涉及Android針對背景圖相關(guān)屬性設(shè)置的操作技巧,需要的朋友可以參考下
    2015-12-12
  • Kotlin 使用高階函數(shù)實現(xiàn)回調(diào)方式

    Kotlin 使用高階函數(shù)實現(xiàn)回調(diào)方式

    這篇文章主要介紹了Kotlin 使用高階函數(shù)實現(xiàn)回調(diào)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-03-03
  • Android-SPI學習筆記

    Android-SPI學習筆記

    這篇文章主要介紹了Android-SPI的相關(guān)資料,幫助大家更好的理解和學習使用Android,感興趣的朋友可以了解下
    2021-02-02
  • Android RecyclerView基本使用詳解

    Android RecyclerView基本使用詳解

    這篇文章主要為大家詳細介紹了Android RecyclerView基本使用的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-02-02

最新評論