16

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

视图模型

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 之后。它没有被观察到。你能告诉我代码有什么问题吗?

更新的视图模型

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

2 回答 2

8

ViewModel 的作用是表示视图的当前状态。LiveData 增加了观察状态变化的能力。您将 LiveData 对象视为在调用身份验证时将响应带回的一种方式。相反,您的身份验证方法应该简单地将凭据作为参数,决定是否让该人登录,如果这样做,更新 LiveData ViewModel 以反映该人已登录,然后观察者将得到这个并且很可能会解雇此视图并显示您想要显示的已验证状态的任何其他部分(例如 LoggedInUsername)。

总而言之:

  • 制作一个名为 CurrentAuthenticatedSession 的类或其他东西,例如一个用户名字段,并以 null 开头
  • 进行身份验证调用时,验证查找用户信息
  • 如果是当前更新 CurrentAuthenticatedSession 的 LiveData 实例
  • 让“currentlyLoggedInUser”字段监听此对象的更新
  • 将该控件的文本设置为字段用户名的值

这是一种方式。因为登录屏幕是瞬态的,所以状态更新的观察者可能被视为多余的。但这就是 ViewModel/LiveData 机制的工作原理。

于 2017-10-31T22:39:03.703 回答
5

我的回答不是对这个问题描述的解决方案,而是对问题标题的解决方案。只是标题。

最初在这里回答

如果您的 LiveData<*> 观察者被多次调用,则意味着您多次调用 livedata.observe(...) 。这发生在我身上,因为我在一个方法中执行 livedata.observe(...) 并且每当用户执行某些操作时都会调用此方法,从而再次观察 liveData。为了解决这个问题,我将 livedata.observe(...) 移动到 onCreate() 生命周期方法。

当时的情景是什么? 该应用程序有一个色板。当用户选择一种颜色时,我必须调用 API 来获取该颜色的产品图像。进行 API 调用并在onColorChanged(). 当用户选择一种新颜色时,onColorChanged()将再次调用,从而再次观察 livedata 的变化。

于 2020-01-17T12:25:41.030 回答