백그라운드 서비스 및 업데이트 UI에서 ViewModel의 LiveData를 업데이트하는 방법 return users;

최근에 구글에서 소개 한 안드로이드 아키텍처를 탐구하고 있습니다. 문서 에서 다음 을 찾았습니다.

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
    }
}

활동은 다음과 같이이 목록에 액세스 할 수 있습니다.

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
        });
    }
}

내 질문은 이렇게 할 것입니다.

  1. loadUsers()기능 내가 먼저 데이터에 대한 데이터베이스 (방)을 확인합니다 경우 비동기 적으로 데이터를 가져 오는 있어요

  2. 거기에서 데이터를 얻지 못하면 웹 서버에서 데이터를 가져 오기 위해 API 호출을 할 것입니다.

  3. 가져온 데이터를 데이터베이스 (Room)에 삽입하고 데이터에 따라 UI를 업데이트하겠습니다.

이를 위해 권장되는 접근 방식은 무엇입니까?

메서드 Service에서 API를 호출 하기 위해 a 를 시작하면 loadUsers()어떻게 그 MutableLiveData<List<User>> users변수를 업데이트 할 수 Service있습니까?



답변

나는 당신이 안드로이드 아키텍처 구성 요소를 사용하고 있다고 가정하고 있습니다 . 실제로 service, asynctask or handler데이터를 업데이트하기 위해 전화 하는 곳은 중요하지 않습니다 . method를 사용하여 서비스 또는 asynctask에서 데이터를 삽입 할 수 있습니다 postValue(..). 수업은 다음과 같습니다.

private void loadUsers() {
    // do async operation to fetch users and use postValue() method
    users.postValue(listOfData)
}

(가)로 users입니다 LiveData, Room데이터베이스가 삽입 된 위치에 관계없이 사용자가 데이터를 제공 할 책임이있다.

Note: 아키텍처와 같은 MVVM에서 저장소는 주로 로컬 데이터 및 원격 데이터를 확인하고 가져 오는 역할을합니다.


답변

MutableLiveData<T>.postValue(T value)백그라운드 스레드에서 메서드를 사용할 수 있습니다 .

private void loadUsers() {
    // do async operation to fetch users and use postValue() method
   users.postValue(listOfData)
}


답변

… loadUsers () 함수에서 데이터를 비동기 적으로 가져오고 있습니다. loadUsers () 메서드에서 API를 호출하는 서비스를 시작하는 경우 해당 서비스에서 MutableLiveData> users 변수를 어떻게 업데이트 할 수 있습니까?

앱이 백그라운드 스레드에서 사용자 데이터를 가져 오는 경우 postValue ( setValue 가 아닌 )가 유용합니다.

loadData 메서드에는 MutableLiveData “users”개체에 대한 참조가 있습니다. loadData 메소드는 또한 어딘가 (예 : 저장소)에서 일부 새로운 사용자 데이터를 가져옵니다.

이제 실행이 백그라운드 스레드에서 이루어지면 MutableLiveData.postValue ()는 MutableLiveData 객체의 관찰자 외부에서 업데이트됩니다.

아마도 다음과 같습니다.

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);
        }
    });

}


답변

상기 살펴보세요 안드로이드 아키텍처 가이드 와 같은 새로운 아키텍처 모듈을 함께 LiveDataViewModel. 그들은이 정확한 문제를 심도있게 논의합니다.

그들의 예에서 그들은 그것을 서비스에 넣지 않습니다. “리포지토리”모듈과 Retrofit을 사용하여 어떻게 해결하는지 살펴보십시오. 하단의 부록에는 네트워크 상태 전달, 오류보고 등 더 완전한 예가 포함되어 있습니다.


답변

Repository에서 API를 호출하는 경우

에서 저장소 :

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;
}

에서 의 ViewModel

public LiveData<LoginResponseModel> getUser() {
    loginResponseModelMutableLiveData = repository.checkLogin(loginRequestModel);
    return loginResponseModelMutableLiveData;
}

에서 활동 / 조각

loginViewModel.getUser().observe(LoginActivity.this, loginResponseModel -> {
        if (loginResponseModel != null) {
            Toast.makeText(LoginActivity.this, loginResponseModel.getUser().getType(), Toast.LENGTH_SHORT).show();
        }
    });

참고 : 여기에서 JAVA_1.8 람다를 사용하면 없이도 사용할 수 있습니다.


답변