myLooper()在异步任务期间不退出

时间:2012-03-13 01:28:27

标签: java android asynchronous

我知道我可能会向后退一步,但还没有找到合适的解决方案,这是我最接近的解决方案。我首先向用户呈现Login视图,并将输入的凭据提交给验证凭据的Web服务,如果登录成功,则返回HTTP 200。成功后,我正在向同一个Web服务发出HTTP JSON请求,以下载JSON对象列表。然后解析这些对象,并将其放入SQLite DB中。大约有100个或更多对象,因此异步任务很吸引人,因此我不会锁定UI。这一点是向用户显示ProgressBar(不确定),说明后台正在进行工作,然后在填充数据库后将它们返回到单独的Intent。以下是代码段:

验证登录并调用登录操作:

switch(statusCode) {
   case 200:
      PrepareLogin doLogin = new PrepareLogin();
      doLogin.execute();
      if (doLogin.getStatus().equals(AsyncTask.Status.FINISHED)) {
         // Redirect to intent?
      }
      break;
   case 401:
      Toast.makeText(Login.this, "Invalid Username/Password", Toast.LENGTH_LONG).show();
}

后台有辅助函数的异步任务:

private class PrepareLogin extends AsyncTask<Void,Void,Void> {
        ProgressDialog dialog;
        @Override
        protected void onPreExecute() {
            dialog = new ProgressDialog(Login.this);
            dialog.setTitle(getString(R.string.get_login_dialog_title));
            dialog.setMessage(getString(R.string.get_login_dialog_message));
            dialog.setIndeterminate(true);
            dialog.setCancelable(false);
            dialog.show();
        }
        @Override
        protected Void doInBackground(Void... params) {
            Looper.myLooper().prepare();
            Looper.myLooper().loop();
            DBHelper dbHelp = new DBHelper(Login.this);
            WSHelper wsHelp = new WSHelper();
            long timeNow = System.currentTimeMillis();
            dbHelp.resetDB(Login.this); // For dev environment only...remove in prod
            dbHelp.create();
            dbHelp.createUser(username, password, timeNow, "false");
            dbHelp.close();
            wsHelp.getEmployees(Login.this, username, password);
            Looper.myLooper().quit();
            return null;
        }
        protected void onPostExecute() {
            Intent myIntent = new Intent(login.getContext(), Main.class);
            startActivityForResult(myIntent, 0);
            dialog.dismiss();
        }
    }

我可以使用Looper.myLooper.prepare()函数来解决“Handler必须准备一个looper”错误的唯一方法。

我可以在日志中看到建立连接并填充数据库,但对话框继续旋转,它永远不会到达异步任务的onPostExecute()功能。它会点击Looper.myLooper().quit();行。

任何建议?

2 个答案:

答案 0 :(得分:0)

如果你得到“Handler必须准备一个looper”错误,很可能你是在错误的上下文中调用AsyncTask。我不记得我曾经需要在任何AsyncTask中显式调用Looper.prepare()函数。一旦你摆脱了looper,它会很好,AsyncTask是Android中最容易使用的类之一。你应该在Login类中发布你的代码(我想它是一个Activity,对吧?)。

我能找到的另一个问题是:

case 200:
        PrepareLogin doLogin = new PrepareLogin();
        doLogin.execute();
        if (doLogin.getStatus().equals(AsyncTask.Status.FINISHED)) {
             // Redirect to intent?
        }
break;

您的doLogin.execute();不应该是阻止通话,因此下一个if保证是错误的,因此重定向永远不会被触发。

答案 1 :(得分:0)

看来我的WSHelper类试图从后台进程对UI进行某种更改。通过从AsyncTask中删除wsHelp初始化并使其成为常量,我能够正常进行。值得注意的是,我将wsHelp.getEmployees()方法的返回值更改为void。