Ostatnio odkrywam architekturę Androida, która została niedawno wprowadzona przez Google. Z dokumentacji znalazłem to:
public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> users;
public LiveData<List<User>> getUsers() {
if (users == null) {
users = new MutableLiveData<List<Users>>();
loadUsers();
}
return users;
}
private void loadUsers() {
// do async operation to fetch users
}
}
działanie może uzyskać dostęp do tej listy w następujący sposób:
public class MyActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
model.getUsers().observe(this, users -> {
// update UI
});
}
}
Moje pytanie brzmi: mam zamiar zrobić to:
w
loadUsers()
funkcji pobieram dane asynchronicznie, gdzie najpierw sprawdzę bazę danych (pokój) pod kątem tych danychJeśli nie otrzymam tam danych, wykonam wywołanie API w celu pobrania danych z serwera WWW.
Wstawię pobrane dane do bazy danych (Pokój) i zaktualizuję interfejs użytkownika zgodnie z danymi.
Jakie jest zalecane podejście, aby to zrobić?
Jeśli zacznę Service
wywoływać interfejs API z loadUsers()
metody, w jaki sposób mogę zaktualizować MutableLiveData<List<User>> users
zmienną z tego Service
?
loadUsers()
zasadzie wywoła repozytorium, aby uzyskać informacje o użytkownikuOdpowiedzi:
Zakładam, że używasz komponentów architektury Androida . W rzeczywistości nie ma znaczenia, dokąd dzwonisz,
service, asynctask or handler
aby zaktualizować dane. Możesz wstawić dane z usługi lub z asynctask przy użyciupostValue(..)
metody. Twoja klasa wyglądałaby tak:private void loadUsers() { // do async operation to fetch users and use postValue() method users.postValue(listOfData) }
Jak
users
jestLiveData
,Room
baza danych jest odpowiedzialny za dostarczanie danych użytkowników, gdziekolwiek jest ona włożona.Note:
W architekturze podobnej do MVVM repozytorium jest głównie odpowiedzialne za sprawdzanie i pobieranie danych lokalnych i danych zdalnych.źródło
LiveData
nie aktualizuje sięusers.postValue(mUsers);
-> Ale czy metoda postValue MutableLiveData jest w stanie zaakceptować LiveData ???value
zamiastpostValue
. Dzięki za odpowiedź.Możesz użyć
MutableLiveData<T>.postValue(T value)
metody z wątku w tle.private void loadUsers() { // do async operation to fetch users and use postValue() method users.postValue(listOfData) }
źródło
.setValue()
nie byłoby to dozwoloneJeśli aplikacja pobiera dane użytkownika w wątku w tle, przydatna będzie funkcja postValue (zamiast setValue ).
W metodzie loadData znajduje się odniesienie do obiektu „users” MutableLiveData. Metoda loadData pobiera również świeże dane użytkownika skądś (na przykład z repozytorium).
Teraz, jeśli wykonanie odbywa się w wątku w tle, MutableLiveData.postValue () aktualizuje poza obserwatorami obiektu MutableLiveData.
Może coś takiego:
private MutableLiveData<List<User>> users; . . . private void loadUsers() { // do async operation to fetch users ExecutorService service = Executors.newSingleThreadExecutor(); service.submit(new Runnable() { @Override public void run() { // on background thread, obtain a fresh list of users List<String> freshUserList = aRepositorySomewhere.getUsers(); // now that you have the fresh user data in freshUserList, // make it available to outside observers of the "users" // MutableLiveData object users.postValue(freshUserList); } }); }
źródło
getUsers()
Metoda repozytorium może wywołać interfejs API dla danych, które są asynchroniczne (może uruchomić usługę lub zadanie asynchroniczne) w takim przypadku w jaki sposób może zwrócić Listę z instrukcji return?Zapoznaj się z przewodnikiem po architekturze systemu Android, który towarzyszy nowym modułom architektury, takim jak
LiveData
iViewModel
. Dokładnie omawiają ten problem.W swoich przykładach nie umieszczają tego w usłudze. Zobacz, jak rozwiązują ten problem za pomocą modułu „repozytorium” i Retrofit. Załączniki na dole zawierają bardziej kompletne przykłady, w tym informowanie o stanie sieci, raportowanie błędów itp.
źródło
Jeśli dzwonisz do swojego api w repozytorium,
W repozytorium :
public MutableLiveData<LoginResponseModel> checkLogin(LoginRequestModel loginRequestModel) { final MutableLiveData<LoginResponseModel> data = new MutableLiveData<>(); apiService.checkLogin(loginRequestModel) .enqueue(new Callback<LoginResponseModel>() { @Override public void onResponse(@NonNull Call<LoginResponseModel> call, @Nullable Response<LoginResponseModel> response) { if (response != null && response.isSuccessful()) { data.postValue(response.body()); Log.i("Response ", response.body().getMessage()); } } @Override public void onFailure(@NonNull Call<LoginResponseModel> call, Throwable t) { data.postValue(null); } }); return data; }
W ViewModel
public LiveData<LoginResponseModel> getUser() { loginResponseModelMutableLiveData = repository.checkLogin(loginRequestModel); return loginResponseModelMutableLiveData; }
W aktywności / fragmencie
loginViewModel.getUser().observe(LoginActivity.this, loginResponseModel -> { if (loginResponseModel != null) { Toast.makeText(LoginActivity.this, loginResponseModel.getUser().getType(), Toast.LENGTH_SHORT).show(); } });
Uwaga: Używając tutaj lambdy JAVA_1.8, możesz używać bez niej
źródło