首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >修改UI线程的2个回调问题

修改UI线程的2个回调问题
EN

Stack Overflow用户
提问于 2016-06-16 10:29:13
回答 2查看 4.3K关注 0票数 0

我正在制作一个简单的材料设计登录屏幕,它显示了一个进度对话框,而改造是获取数据。

我最近升级到改造2,所以我对此非常陌生。

我的LoginActivity代码:

代码语言:javascript
复制
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.
    }

以及LoginActivity中的其他功能:

代码语言:javascript
复制
@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)类的代码:

代码语言:javascript
复制
public void login(String username, String password, final LoginActivity loginActivity){
    LoginUser loginUser = new LoginUser(username, password);

    Call<Username> call = apiService.login(loginUser);
    Log.d(TAG, call.toString());
    call.enqueue(new Callback<Username>() {
       @Override
       public void onResponse(Call<Username> call, Response<Username> response) {
           Log.d(TAG, "Responsecode : " + response.code());
           try {
               Thread.sleep(2000); //To test if the progressdialog actually shows up
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
           if(response.code()==200){
               loginActivity.loginOK();
           } else {
               loginActivity.loginFail();
           }
       }

       @Override
       public void onFailure(Call<Username> call, Throwable t) {
           Log.d(TAG, "Failed: " + t.getMessage());
           loginActivity.loginFail();
       }
   });
}

现在我不断地收到错误,例如:- android.util.AndroidRuntimeException:动画师只能在活套线程上运行(关于loginbutton) - java.lang.RuntimeException:无法在没有调用Looper.prepare() (关于toastCreator)的线程中创建处理程序。

我理解是什么导致了这个问题(来自retrofit 2的异步线程正在执行调用),当它应该将调用传递给ui线程时。我的问题是,解决这个问题的最好办法是什么?当然,我可以与CountdownLatch一起破解一些代码,并以强制同步的形式运行整个异步调用,但这并不是我想要的。我应该使用处理程序吗?如果是的话,实现这一点的最佳方式是什么?

所有代码都可用:https://github.com/mathieudevos/pinkiponki-app

期待答案!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-06-17 10:07:17

好吧,既然没有人正确回答这个问题,就这样吧!

使用一个处理程序并向它发送消息似乎就能做到这一点。

在onCreate方法中:

代码语言:javascript
复制
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();
            }
        }
    };

在我的网络逻辑课上:

代码语言:javascript
复制
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();
       }
}

因为这是在mainLooper上运行的,所以我可以在任何这些函数中使用UI。这应该是正确的答案。

票数 5
EN

Stack Overflow用户

发布于 2016-06-16 10:39:16

修改onResponse可以在UI线程上工作,因此您的thread.sleep()将为您带来问题。

代码语言:javascript
复制
 Thread.sleep(2000); //This line must not be on UI thread.

如果您需要一些延迟,可以轻松地使用处理程序。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37856571

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档