使っています - Transformations.switchMap
ViewModelで、フラグメントで観察されるLiveData
コレクションは、code
パラメーターの変更に反応します。
これは完全に機能します:
public class MyViewModel extends AndroidViewModel {
private final LiveData<DayPrices> dayPrices;
private final MutableLiveData<String> code = new MutableLiveData<>();
// private final MutableLiveData<Integer> nbDays = new MutableLiveData<>();
private final DBManager dbManager;
public MyViewModel(Application application) {
super(application);
dbManager = new DBManager(application.getApplicationContext());
dayPrices = Transformations.switchMap(
code,
value -> dbManager.getDayPriceData(value/*, nbDays*/)
);
}
public LiveData<DayPrices> getDayPrices() {
return dayPrices;
}
public void setCode(String code) {
this.code.setValue(code);
}
/*public void setNbDays(int nbDays) {
this.nbDays.setValue(nbDays);
}*/
}
public class MyFragment extends Fragment {
private MyViewModel myViewModel;
myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
myViewModel.setCode("SO");
//myViewModel.setNbDays(30);
myViewModel.getDayPrices().observe(MyFragment.this, dataList -> {
// update UI with data from dataList
});
}
問題
ここで別のパラメーター(上記のコードでコメントされたnbDays
)が必要なので、LiveData
オブジェクトは両方のパラメーターの変更(code
とnbDays
)に反応します。
変換を連鎖するにはどうすればよいですか?
MediatorLiveData を示している読み物もありますが、それで問題は解決しません(2つのパラメーターで単一のDB関数を呼び出す必要があり、2つのliveDataをマージする必要はありません)。
そこで、switchMap
の代わりにこれを試しましたが、code
とnbDays
は常にnullです。
dayPrices.addSource(
dbManager.getDayPriceData(code.getValue(), nbDays.getValue),
apiResponse -> dayPrices.setValue(apiResponse)
);
1つの解決策は、オブジェクトを単一のパラメータとして渡すことです。これには簡単な解決策があると確信しています。
ソース: https://plus.google.com/+MichielPijnackerHordijk/posts/QGXF9gRomVi
switchMap()
に対して複数のトリガーを使用するには、カスタムMediatorLiveData
を使用してLiveDataオブジェクトの組み合わせを確認する必要があります-
class CustomLiveData extends MediatorLiveData<Pair<String, Integer>> {
public CustomLiveData(LiveData<String> code, LiveData<Integer> nbDays) {
addSource(code, new Observer<String>() {
public void onChanged(@Nullable String first) {
setValue(Pair.create(first, nbDays.getValue()));
}
});
addSource(nbDays, new Observer<Integer>() {
public void onChanged(@Nullable Integer second) {
setValue(Pair.create(code.getValue(), second));
}
});
}
}
その後、これを行うことができます-
CustomLiveData trigger = new CustomLiveData(code, nbDays);
LiveData<DayPrices> dayPrices = Transformations.switchMap(trigger,
value -> dbManager.getDayPriceData(value.first, value.second));
Kotlinを使用しており、ジェネリックを使用する場合:
class DoubleTrigger<A, B>(a: LiveData<A>, b: LiveData<B>) : MediatorLiveData<Pair<A?, B?>>() {
init {
addSource(a) { value = it to b.value }
addSource(b) { value = a.value to it }
}
}
次に:
val dayPrices = Transformations.switchMap(DoubleTrigger(code, nbDays)) {
dbManager.getDayPriceData(it.first, it.second)
}
@ jL4によって提案されたカスタムMediatorLiveData
はうまく機能し、おそらくソリューションです。
私は、内部クラスを使用して、合成されたフィルター値を表すことであると思う最も単純なソリューションを共有したかっただけです。
public class MyViewModel extends AndroidViewModel {
private final LiveData<DayPrices> dayPrices;
private final DBManager dbManager;
private final MutableLiveData<DayPriceFilter> dayPriceFilter;
public MyViewModel(Application application) {
super(application);
dbManager = new DBManager(application.getApplicationContext());
dayPriceFilter = new MutableLiveData<>();
dayPrices = Transformations.switchMap(dayPriceFilter, input -> dbManager.getDayPriceData(input.code, input.nbDays));
}
public LiveData<DayPrices> getDayPrices() {
return dayPrices;
}
public void setDayPriceFilter(String code, int nbDays) {
DayPriceFilter update = new DayPriceFilter(code, nbDays);
if (Objects.equals(dayPriceFilter.getValue(), update)) {
return;
}
dayPriceFilter.setValue(update);
}
static class DayPriceFilter {
final String code;
final int nbDays;
DayPriceFilter(String code, int nbDays) {
this.code = code == null ? null : code.trim();
this.nbDays = nbDays;
}
}
}
次に、アクティビティ/フラグメントで:
public class MyFragment extends Fragment {
private MyViewModel myViewModel;
myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
myViewModel.setDayPriceFilter("SO", 365);
myViewModel.getDayPrices().observe(MyFragment.this, dataList -> {
// update UI with data from dataList
});
}
同様の問題に直面しました。これを解決するには2つの方法があります。
MediatorLiveData
を使用しますRxJavaがわからない場合は、カスタムMediatorLiveData
クラスを記述することをお勧めします。カスタムMediatorLiveData
クラスの記述方法については、次の例をご覧ください。 https://Gist.github.com/AkshayChordiya/a79bfcc422fd27d52b15cdafc55eac6b