2017-06-12 28 views
6

Mam wiele ViewHolders, które działają jako oddzielne widoki wewnątrz pionowej RecyclerView. Ćwiczę z nowym komponentem Architecture Components ViewModel.Jak korzystać z modułu Architecture Components ViewModel wewnątrz adaptera RecyclerView?

wewnątrz mojego ViewModel Mam kilka list MutableLiveData, które chcę obserwować. ale jak można nazwać

ViewModelProviders.of((AppCompatActivity)getActivity()).get(FilterViewModel.class) 

i

mFilterViewModel.getCountries().observe(this, new Observer<ArrayList<TagModel>>() { 
      @Override 
      public void onChanged(@Nullable ArrayList<TagModel> tagModels) { 

      } 
     }); 

bez przecieka aktywność lub zapisać aktywność wewnątrz adaptera.

mój ViewModel

public class FilterViewModel extends ViewModel { 

private final MutableLiveData<ArrayList<TagModel>> mCountries; 
private final MutableLiveData<ArrayList<TagModel>> mSelectedCountryProvinceList; 
private final MutableLiveData<ArrayList<TagModel>> mDistanceList; 

public FilterViewModel(){ 

    mCountries = new MutableLiveData<>(); 
    mSelectedCountryProvinceList = new MutableLiveData<>(); 
    mDistanceList = new MutableLiveData<>(); 

    TagStore.getInstance().subscribe(new StoreObserver<TagSearchList>() { 
     @Override 
     public void update(TagSearchList object) { 
      mCountries.setValue(object.getCountries()); 
     } 

     @Override 
     public void update(int id, TagSearchList object) { 
      if (id == 5){ 
       TagStore.getInstance().unSubcribe(this); 
       update(object); 
      } 
     } 

     @Override 
     public void error(String error) { 

     } 
    }).get(5,"parent"); 

    TagStore.getInstance().subscribe(new StoreObserver<TagSearchList>() { 
     @Override 
     public void update(TagSearchList object) { 
      mSelectedCountryProvinceList.setValue(object.toList()); 
     } 

     @Override 
     public void update(int id, TagSearchList object) { 
      if (id == 6){ 
       TagStore.getInstance().unSubcribe(this); 
       update(object); 
      } 
     } 

     @Override 
     public void error(String error) { 

     } 
    }).get(6,"parent"); 

    TagStore.getInstance().subscribe(new StoreObserver<TagSearchList>() { 
     @Override 
     public void update(TagSearchList object) { 
      mDistanceList.setValue(object.toList()); 
     } 

     @Override 
     public void update(int id, TagSearchList object) { 
      if (id == 51){ 
       TagStore.getInstance().unSubcribe(this); 
       update(object); 
      } 
     } 

     @Override 
     public void error(String error) { 

     } 
    }).get(51,"parent"); 

} 

public void selectCountry(final TagModel country){ 
    TagStore.getInstance().subscribe(new StoreObserver<TagSearchList>() { 
     @Override 
     public void update(TagSearchList object) { 
      mSelectedCountryProvinceList.setValue(object.toList()); 
     } 

     @Override 
     public void update(int id, TagSearchList object) { 
      if (id == country.getId()){ 
       TagStore.getInstance().unSubcribe(this); 
       update(object); 
      } 
     } 

     @Override 
     public void error(String error) { 

     } 
    }).get(country.getId(),"parent"); 
} 

public LiveData<ArrayList<TagModel>> getCountries(){ 
    return mCountries; 
} 

public LiveData<ArrayList<TagModel>> getDistances(){ 
    return mDistanceList; 
} 

public LiveData<ArrayList<TagModel>> getProvinces(){ 
    return mSelectedCountryProvinceList; 
} 

}

+0

Witam. Dlaczego zamiast tego nie chcesz użyć funkcji powiązania danych Androida? – JuliaKo

+0

Witam @JuliaKo, nie jest moją intencją, aby zmienić moją aplikację na MVVM. W tej chwili używam MVP. Chcę użyć klasy ViewModel ze strukturą MVP, aby rozwiązać problemy z cyklem życia, przeładować dane i niepotrzebne obserwacje. –

+0

Myślę, że to, czego potrzebujesz, to zaimplementowanie adaptera wiążącego, a zespół Google zamierza uświadomić cykl życia danych, ale aby to się wydarzyło, cykl życia musi osiągnąć 1.0 stabilny interfejs API. Możesz obejrzeć otwarty problem tutaj: https://github.com/googlesamples/android-architecture-components/issues/34 – JuliaKo

Odpowiedz

0

Moje rozwiązanie tego problemu jest;

  • utworzyć nową zmienną (ViewModel) dla układu (układ fragment lub aktywności)
  • w swojej działalności lub fragmentu uzyskać instancję Twojej ViewModel z ViewModelProviders
  • trzymać dane, które wypełnia recyclerView w MutableLiveData i obserwuj go i napełnij adapter urządzenia recyklingowego ViewView z wartością, którą zaobserwowałeś,

tutaj musisz zachować ostrożność, aby nie tworzyć instancji adaptera w metodzie obserwacji. jeśli utworzysz go w metodzie obserwacyjnej, spowoduje to wyciek

+0

Czy możesz wyjaśnić, dlaczego tworzenie adaptera w metodzie obserwacyjnej powoduje wyciek? –

0

Tylko dla przyszłych czytelników. Roztwór można zaoferować:

  • w aktywności, tworzenia ViewModelProvider instancję:

    ViewModelProvider Provider = ViewModelProviders.of (to);

  • Następnie przekazaniem go do konstruktora adaptera

  • W klasie ViewHolder adaptera utworzyć konstruktor, który odbywa instancji FilterBinding i wykonuje

    super(binding.getRoot());

  • metoda
  • Wewnątrz onCreateViewHolder tylko instancję powiązanie z, na przykład, DataBindingUtil.inflate (...) i zwrócenie instancji ViewHolder, która przejęła to powiązanie w zależności od jego konstruktora;

  • We wnętrzu ViewHolder klasy tworzymy metodę, która pobiera TagModel (lub od Ciebie zależy co dokładnie, ponieważ y nie widziałem twojego adaptera i nie rozumiem dokładnie, co się dzieje w twojej logice) wiązania:

    if (mBindings == null) { FilterViewModel vm = viewModelProvider.get(FilterViewModel.class); /*or instantiate? I am not sure about caching here, honestly. If you chose instantiating, then passing ViewModelProvider to the adapter is not needed*/ mBindings.setViewModel(vm); } mBindings.getViewModel(setItem(item)); mBindings.executePendingBindings();

  • I, na koniec, po prostu wykonywać metodę wiązania tego viewholder jest wewnątrz onBindViewHolder (...)

Szczerze mówiąc, nie czuję w ten sposób przyjemności i piękna, ale to wszystko, co mogę zaoferować.