2016-12-02 32 views
4

データバインディングライブラリがBindingAdapterの実行順序を決定する方法を理解する必要があります。ビュー用に2つのBindingAdapterがあり、Viewに両方のBindingAdapterに対応する属性がある場合、最初に実行されるアダプタはどのように決定されますか?私の場合は執行の命令が重要なので、私は尋ねる。Android BindingAdapter実行順序?

私はBindingAdapter/sの次き:

public class SpinnerBindingAdapter { 

    @BindingAdapter(value = {"entries"}) 
    public static void setEntries(Spinner spinner, List<? extends SpinnerItem> spinnerItems) { 

     for (int i = 0; i < spinnerItems.size(); i++) { 
      spinnerItems.get(i).setIndex(i); 
     } 
     ArrayAdapter<? extends SpinnerItem> adapter = 
       new ArrayAdapter<>(spinner.getContext(), R.layout.spinner_item, spinnerItems); 
     spinner.setAdapter(adapter); 
    } 

    @InverseBindingAdapter(attribute = "selectedItem", event = "selectedItemAttrChanged") 
    public static Object getSelectedItem(Spinner spinner) { 

     Object selectedItem = spinner.getSelectedItem(); 

     return selectedItem; 
    } 

    @BindingAdapter(value = {"selectedItem"}) 
    public static void setSelectedItem(Spinner spinner, SpinnerItem spinnerItem) { 
     if (spinner.getAdapter() == null) { 
      return; 
     } 
     // Other code omitted for simplicity 
    } 

    @BindingAdapter(value = {"selectedItemAttrChanged"}, requireAll = false) 
    public static void setOnItemSelectedListener(Spinner spinner, final InverseBindingListener selectedItemChange) { 
     if (selectedItemChange == null) { 
      spinner.setOnItemSelectedListener(null); 
     } else { 
      spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 

       @Override 
       public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 
        selectedItemChange.onChange(); 
       } 

       @Override 
       public void onNothingSelected(AdapterView<?> parent) { 

       } 
      }); 
     } 
    } 
} 

そして、ここでは、私はスピナーを移入し、選択範囲を設定する方法である:

<Spinner 
    android:id="@+id/spinner_system_activity_edit_tracker_unit" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_gravity="fill_horizontal" 
    app:entries="@{DatabaseModel.queryForAll()}" 
    app:selectedItem="@={object.selectedItem}"/> 

DatabaseModel.queryForAllは、データベースを照会する静的メソッドでありますBindingAdapterに渡されるオブジェクトのリストを返します。 BindingAdapterはこのリストを取得し、各アイテムをインデックスで更新し、スピナーのアダプタとして設定します。

なぜなら、「setSelectedItem」BindingAdapterは常に最初に呼び出されます。最初にエントリを初期化する必要があるため、これは望ましくありません。最初に初期化されていない場合は、setSelectedItemが最初に呼び出されたときにspinner.getAdapter()がnullになります。つまり、以前に保存された選択は復元されません。

答えて

8

Android Data Bindingでの実行順序は保証されていません。このため、複数の属性に依存するバインドアダプタをマージする必要があります。あなたの場合、selectedItemと項目のバインディングアダプタをマージする必要があります。

@BindingAdapter(value = {"selectedItem", "entries"}, requireAll = false) 
public static void setSelectedItem(Spinner spinner, SpinnerItem spinnerItem, 
     List<? extends SpinnerItem> spinnerItems) { 
    // Set entries attribute when provided 
    if (spinnerItems != null) { 
     for (int i = 0; i < spinnerItems.size(); i++) { 
      spinnerItems.get(i).setIndex(i); 
     } 
     ArrayAdapter<? extends SpinnerItem> adapter = 
      new ArrayAdapter<>(spinner.getContext(), R.layout.spinner_item, spinnerItems); 
     spinner.setAdapter(adapter); 
    } 
    // set selectedItem attribute when provided 
    if (spinnerItem != null) { 
     if (spinner.getAdapter() == null) { 
      return; 
     } 
     // Other code omitted for simplicity 
    } 
} 
+0

ありがとう、非常に良い答え!これからもいい結果を出し続けてください! – chaser