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

标签 java android asynchronous

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

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

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() 函数。

我可以在日志中看到已建立连接并填充数据库,但对话框继续旋转,并且从未到达异步任务的 onPostExecute() 函数。但它到达了 Looper.myLooper().quit(); 行。

有什么建议吗?

最佳答案

如果您收到“处理程序必须准备循环程序”错误,则很可能您在错误的上下文中调用 AsyncTask。我不记得我曾经需要在任何 AsyncTask 中显式调用 Looper.prepare() 函数。一旦你摆脱了循环器,那就好了,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肯定是错误的,因此重定向永远不会触发。

关于java - myLooper() 在异步任务期间不会退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9677167/

相关文章:

C# - 将异步任务从一种类型转换为另一种类型

java - Java如何从域名中获取IP地址?

java - 尝试使用通过 Iterator 检索的对象时出现 NullPointerException

android - 将 PendingIntent 中的小部件的额外内容传递给 Activity

android - 未在 "Network tickle"上调用 SyncAdapter

IOS SWIFT - 服务调用完成获取时返回响应数据

java - 如何使用 .properties 文件中的值在 spring bean 中初始化一个集合

java - 定位图像以适合所有尺寸的屏幕

android - 使用 Fabric SDK 获取 Twitter 用户电子邮件

grails - Groovy PromiseMap - 我可以限制异步线程池吗?