アプリでAndroid Architecture Components
を使用しています。ログインアクティビティで、ログインが失敗したときにダイアログが表示されます。
ライブデータのため、ダイアログは3回以上表示されています。ログを追加したところ、livedata
が複数回呼び出されていることがわかりました。
この問題を解決するにはどうすればよいですか?
[〜#〜]アクティビティ[〜#〜]
mViewModel.authenticate(token, binding.inputPassword.getText().toString()).observe(LoginActivity.this, apiResponse -> {
progress.dismiss();
if (apiResponse != null) {
if (apiResponse.getError() != null) {
Log.e("Login", "Network Failure");
} else {
if (apiResponse.getAuthuser().getStatus().equals("VALID")) {
PrefUtils.saveUserToPrefs(LoginActivity.this, apiResponse.getAuthuser());
finish();
} else if (apiResponse.getAuthuser().getStatus().equals("INVALID")) {
Log.e("LOGIN Issue ", "Showing Dialog" + apiResponse.getAuthuser().getStatus());
loginFailure();
}
}
}
});
ViewModel
class LoginActivityViewModel extends ViewModel {
private final FarmerRepository farmerRepository;
private MediatorLiveData<ApiResponse> mApiResponse;
LoginActivityViewModel(FarmerRepository repository) {
mApiResponse = new MediatorLiveData<>();
farmerRepository = repository;
}
MediatorLiveData<ApiResponse> authenticate(String encryptedMobile, String pwd) {
mApiResponse.addSource(
farmerRepository.authenticate(encryptedMobile, pwd),
apiResponse -> mApiResponse.setValue(apiResponse)
);
return mApiResponse;
}
}
[〜#〜] logcat [〜#〜]
11-01 00:13:31.265 24386-24386 E/LOGIN Issue: Showing DialogINVALID
11-01 00:13:31.312 24386-24386 E/LOGIN Issue: Showing DialogINVALID
11-01 00:13:37.034 24386-24386 E/LOGIN Issue: Showing DialogINVALID
11-01 00:13:38.196 24386-24386 E/LOGIN Issue: Showing DialogINVALID
11-01 00:13:38.234 24386-24386 E/LOGIN Issue: Showing DialogINVALID
11-01 00:13:38.273 24386-24386 E/LOGIN Issue: Showing DialogINVALID
[〜#〜]更新[〜#〜]
SingleLiveEventを使用した後。観測されていません。コードのどこが悪いのか教えていただけますか?
更新されたViewModel
class LoginActivityViewModel extends ViewModel {
private final FarmerRepository farmerRepository;
private MediatorLiveData<ApiResponse> mApiResponse;
private SingleLiveEvent<ApiResponse> mMsgUpdate;
LoginActivityViewModel(FarmerRepository repository) {
mApiResponse = new MediatorLiveData<>();
farmerRepository = repository;
mMsgUpdate = new SingleLiveEvent<>();
}
SingleLiveEvent<ApiResponse> authenticate(String encryptedMobile, String pwd) {
mApiResponse.addSource(
farmerRepository.authenticate(encryptedMobile, pwd),
apiResponse -> mMsgUpdate.setValue(apiResponse)
);
return mMsgUpdate;
}
}
ViewModelの役割は、ビューの現在の状態を表すことです。 LiveDataは、状態の変化を観察する機能を追加します。認証のための呼び出しで応答を返す方法としてLiveDataオブジェクトを処理しています。代わりに、認証メソッドは資格情報をパラメーターとして受け取り、ユーザーをログインさせるかどうかを決定する必要があります。そうする場合は、LiveData ViewModelを更新して、ユーザーがログインしていることを反映させると、オブザーバーはこれを取得し、ほとんどの場合、却下します。このビューには、表示する認証済み状態の他の部分(LoggedInUsernameなど)が表示されます。
要約すると:
それは一つの方法です。ログイン画面は一時的なものであるため、状態更新のオブザーバーは不必要であると見なされる場合があります。しかし、それがViewModel/LiveDataメカニズムが機能する方法です。
私の回答は、この質問の説明に対する解決策ではなく、質問のタイトルに対する解決策です。タイトルだけ。
元の回答 ここ
LiveData <*>のオブザーバーが複数回呼び出されている場合、それはlivedata.observe(...)を複数回呼び出していることを意味します。これはメソッドでlivedata.observe(...)を実行していて、ユーザーがなんらかのアクションを実行するたびにこのメソッドを呼び出していたため、liveDataを再度観察しているときに私に起こりました。これを解決するために、livedata.observe(...)をonCreate()ライフサイクルメソッドに移動しました。
シナリオは何でしたか?アプリには色見本があります。ユーザーが色を選択すると、その色の商品画像を取得するためにAPIを呼び出す必要がありました。つまり、API呼び出しを行い、onColorChanged()
でlivedataを監視していました。ユーザーが新しい色を選択すると、onColorChanged()
が再度呼び出され、livedataの変更を再度監視します。