Android 使用UI线程改进2个回调问题
我正在制作一个简单的材料设计登录屏幕,在改造获取数据时显示一个进度对话框 我最近升级到了翻新2,所以我对这一点很陌生 我的LoginActivity代码:Android 使用UI线程改进2个回调问题,android,retrofit2,android-handler,ui-thread,Android,Retrofit2,Android Handler,Ui Thread,我正在制作一个简单的材料设计登录屏幕,在改造获取数据时显示一个进度对话框 我最近升级到了翻新2,所以我对这一点很陌生 我的LoginActivity代码: private void login(){ Log.d(TAG, "Attempting login"); if(!validate()){ onLoginFailure(); return; } login_button.se
private void login(){
Log.d(TAG, "Attempting login");
if(!validate()){
onLoginFailure();
return;
}
login_button.setEnabled(false);
progressDialog = new ProgressDialog(LoginActivity.this, R.style.AppTheme_Dark_Dialog);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Authenticating...");
progressDialog.show();
String username = _usernameText.getText().toString().toLowerCase(); //all usernames are lowercase only
String password = _passwordText.getText().toString();
//here we handle the NWL section.
startTime = System.currentTimeMillis();
NWL.login(username, password, this); //This runs async to UI anyway.
}
@BindView(R.id.login_button)
Button login_button;
public void loginOK() {
progressDialog.dismiss();
login_button.setEnabled(true);
toastCreator.showToastLong("Login OK");
Log.d(TAG, "Total time: " + (System.currentTimeMillis()-startTime));
}
以及LoginActivity中的其他功能:
private void login(){
Log.d(TAG, "Attempting login");
if(!validate()){
onLoginFailure();
return;
}
login_button.setEnabled(false);
progressDialog = new ProgressDialog(LoginActivity.this, R.style.AppTheme_Dark_Dialog);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Authenticating...");
progressDialog.show();
String username = _usernameText.getText().toString().toLowerCase(); //all usernames are lowercase only
String password = _passwordText.getText().toString();
//here we handle the NWL section.
startTime = System.currentTimeMillis();
NWL.login(username, password, this); //This runs async to UI anyway.
}
@BindView(R.id.login_button)
Button login_button;
public void loginOK() {
progressDialog.dismiss();
login_button.setEnabled(true);
toastCreator.showToastLong("Login OK");
Log.d(TAG, "Total time: " + (System.currentTimeMillis()-startTime));
}
我的NetworkLogic(NWL)类中的代码:
public void登录(字符串用户名、字符串密码、最终登录活动LoginActivity){
LoginUser LoginUser=新登录用户(用户名、密码);
Call Call=apiService.login(loginUser);
Log.d(TAG,call.toString());
call.enqueue(新回调(){
@凌驾
公共void onResponse(调用、响应){
Log.d(标记“Responsecode:+response.code());
试一试{
Thread.sleep(2000);//测试progressdialog是否实际显示
}捕捉(中断异常e){
e、 printStackTrace();
}
if(response.code()==200){
loginActivity.loginOK();
}否则{
loginActivity.loginFail();
}
}
@凌驾
失败时公共无效(调用调用,可丢弃的t){
Log.d(标记“Failed:+t.getMessage());
loginActivity.loginFail();
}
});
}
现在,我不断收到错误,例如:
-android.util.AndroidRuntimeException:动画师只能在活套线程上运行(关于登录按钮)
-java.lang.RuntimeException:无法在未调用Looper.prepare()的线程内创建处理程序(关于toastCreator)
我理解问题的原因(来自改型2的异步线程正在进行调用),它应该将调用传递给ui线程。
我的问题是,处理这个问题的最佳解决方案是什么?当然,我可以用CountdownLatch一起破解一些代码,并以强制同步的方式运行整个异步调用,但这并不是我真正想要的。
我应该使用处理程序吗?如果是的话,实施这一点的最佳方式是什么
所有代码均可用:
期待答案 改型onResponse在UI线程上工作,所以您的thread.sleep()会给您带来问题
Thread.sleep(2000); //This line must not be on UI thread.
如果您需要一些延迟,您可以轻松地使用handler。好的,因为没有人正确地回答了这个问题,现在开始 使用处理程序并向其发送消息似乎可以达到目的 在onCreate方法中:
handler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg){
switch (msg.what){
case 200:
//Got the good response
loginOK();
break;
case 401:
loginFail();
break;
default:
loginFail();
}
}
};
在我的networklogic课程中:
Call<Username> call = apiService.login(userObject);
call.enqueue(new Callback<Username>() {
@Override
public void onResponse(Call<Username> call, Response<Username> response) {
Log.d(TAG, "Responsecode: " + response.code());
Message msg = handler.obtainMessage(response.code());
msg.sendToTarget();
}
@Override
public void onFailure(Call<Username> call, Throwable t) {
Log.d(TAG, "Failed: " + t.getMessage());
Message msg = handler.obtainMessage(0); //0 for errors
msg.sendToTarget();
}
}
Call Call=apiService.login(userObject);
call.enqueue(新回调(){
@凌驾
公共void onResponse(调用、响应){
Log.d(标记“Responsecode:+response.code());
Message msg=handler.obtainMessage(response.code());
msg.sendToTarget();
}
@凌驾
失败时公共无效(调用调用,可丢弃的t){
Log.d(标记“Failed:+t.getMessage());
Message msg=handler.obtainMessage(0);//错误为0
msg.sendToTarget();
}
}
因为这是在mainLooper上运行的,所以我可以在这些函数中任意使用我的UI。
这应该是正确答案。删除thread.sleep仍然会导致我的登录按钮出现问题。setEnabled(true)。错误:android.util.AndroidRuntimeException:动画师只能在活套线程上运行请发送完整的堆栈跟踪。错误代码(故意提供错误密码):