替换嵌套的AsyncTasks

时间:2018-04-27 08:28:37

标签: android android-asynctask nested

在我的Android应用程序中,我有几个活动都连接到一个服务。此服务建立与服务器的连接,并处理数据的发送和检索(大多数情况下为xml文件)。在我的活动内部,我调用AsyncTask中的服务函数,因为我需要根据服务器的答案执行以下操作。以下是结构示例:

String xmlString = "<myXmlString><myDataObject></myDataObject></myXmlString>";

final AsyncTask<Void, Void, Boolean> myTask = new AsyncTask<Void, Void, Boolean>() {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();

        showProgressDialog("Send Data...");
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        int rc = mService.callMethod("MYFUNCTION", xmlString);
        if (rc == 0) {
            return true;
        }
        else {
            return false;
        }
    }

    @Override
    protected void onPostExecute(Boolean success) {
        hideProgressDialog();

        if (success) {
            // handle received data
            // here it also might occur that another AsyncTask is called
            // e.g.: final AsyncTask<Void, Void, Boolean> nestedTask = new AsyncTask<Void, Void, Boolean>() { ... }
        } else {
            // handle error
        }
    }
};

myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

Handler handler = new Handler();
Runnable taskCanceler = new Runnable() {
    @Override
    public void run() {
        if (myTask.getStatus() == AsyncTask.Status.RUNNING) {
            myTask.cancel(true);

            hideProgressDialog();
        }
    }
};
handler.postDelayed(taskCanceler, 15000);

由于我更新了Android Studio,因此它说“此AsyncTask应该是静态的,否则可能会发生泄漏”。此外,嵌套的AsyncTasks有时会非常混乱,但它们相互依赖,所以我真的不知道如何将这些任务更改为静态类。我是否应该根据自己的需要使用不同的方法,还是可以将它们转换为静态类并保持嵌套逻辑的存活?

我希望我可以清楚地解决问题。提前谢谢!

4 个答案:

答案 0 :(得分:2)

引入Asyntasks作为同步的背景方法,能够在结束时将结果发布到主线程。但是,当逻辑复杂时,它们有很大的局限性。

它们很难正确取消,如果使用不当,它们可能会泄漏内存,并且在运行多个操作时使用它们很麻烦。

最后,他们对你可以同时执行的数量有一个硬限制。

Here,你会找到一个库列表,你可以用它来代替Asynctask

如果您是一位经验丰富的程序员,那么我建议您先走一步,使用以下技术之一:

RxJava:这在过去几年中已成为Android开发的主流。它将帮助您以被动方式处理业务逻辑和API调用。学习曲线在开始时非常陡峭,但稍后会使您的生活更轻松。 这是一个介绍tutorial

Kotlin Coroutines :如果你进入kotlin协同程序提供了一种处理并发的简单方法。在这里你可以找到一些tutorials

答案 1 :(得分:1)

您似乎愿意更改您的网络服务访问逻辑。

您应该阅读有关Rxjava / RxKotlin的内容,并使用这些技术进行快速重构。 起初它看起来很复杂,但请相信我,一旦Rx你永远不会回去。

See more here

答案 2 :(得分:1)

   private static class TASK_NAME extends AsyncTask<Void, Void, Boolean> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            showProgressDialog("Send Data...");
        }

        @Override
        protected Boolean doInBackground(Void... params) {
            int rc = mService.callMethod("MYFUNCTION", xmlString);
            if (rc == 0) {
                return true;
            }
            else {
                return false;
            }
        }

        @Override
        protected void onPostExecute(Boolean success) {
            hideProgressDialog();

            if (success) {
                // handle received data
                // here it also might occur that another AsyncTask is called
                // e.g.: final AsyncTask<Void, Void, Boolean> nestedTask = new AsyncTask<Void, Void, Boolean>() { ... }
            } else {
                // handle error
            }
        }
    };

然后OnCreateView就像这样调用它:

new TASK_NAME().execute();

答案 3 :(得分:1)

如果您了解足以完成的基本线程,请不要使用AsyncTasks。 AsyncTasks是帮助者,他们没有那么多帮助。在服务中添加以下内容。您通常会传递一个共享接口(lambda会在这里做得很好,但是Java 7)会触发响应。然后服务为您执行线程处理。毕竟,在服务与服务器通信的情况下,它总能发生。无论如何,它总是需要在一个线程中这样做。

    HttpFetch.get(url, new UIResponse() {
        @Override
        public void response(String header, String content) {
        }
    },this);

因为它使用静态类进行Http工作,所以没有泄漏,你可以调用它并获得你想要的响应数据。而且因为它是相同的静态类,你显然可以将它们嵌入你的心中。因此,您向响应发送请求和类,并实现响应类。

例如,从我做那件事之后的其余部分:

public static void get(final URL urir, final Response response, final Activity activity) {
    Runnable run = new Runnable() {
        @Override
        public void run() {
            HttpURLConnection urlConnection = null;
            try {
                urlConnection = (HttpURLConnection) urir.openConnection();
                InputStream stream = new BufferedInputStream(urlConnection.getInputStream());
                final String content = convertStreamToString(stream);
                final String header = urlConnection.getResponseMessage();
                stream.close();

                activity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        response.response(header, content);
                    }
                });
            } catch (final IOException e) {
                activity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        response.error(e);
                    }
                });
            } finally {
                if (urlConnection != null) urlConnection.disconnect();
            }
        }
    };
    Thread thread = new Thread(run);
    thread.start();
}

static String convertStreamToString(java.io.InputStream is) {
    java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
    return s.hasNext() ? s.next() : "";
}


public interface Response {
    void response(String header, String content);
    void error(IOException exception);
}

像RxJava这样的其他类可能会做同样的事情。只需提交一个带有响应功能的请求,然后在服务中进行线程处理即可。