在我的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有时会非常混乱,但它们相互依赖,所以我真的不知道如何将这些任务更改为静态类。我是否应该根据自己的需要使用不同的方法,还是可以将它们转换为静态类并保持嵌套逻辑的存活?
我希望我可以清楚地解决问题。提前谢谢!
答案 0 :(得分:2)
引入Asyntasks作为同步的背景方法,能够在结束时将结果发布到主线程。但是,当逻辑复杂时,它们有很大的局限性。
它们很难正确取消,如果使用不当,它们可能会泄漏内存,并且在运行多个操作时使用它们很麻烦。
最后,他们对你可以同时执行的数量有一个硬限制。
Here,你会找到一个库列表,你可以用它来代替Asynctask
如果您是一位经验丰富的程序员,那么我建议您先走一步,使用以下技术之一:
RxJava:这在过去几年中已成为Android开发的主流。它将帮助您以被动方式处理业务逻辑和API调用。学习曲线在开始时非常陡峭,但稍后会使您的生活更轻松。 这是一个介绍tutorial
Kotlin Coroutines :如果你进入kotlin协同程序提供了一种处理并发的简单方法。在这里你可以找到一些tutorials
答案 1 :(得分:1)
您似乎愿意更改您的网络服务访问逻辑。
您应该阅读有关Rxjava / RxKotlin的内容,并使用这些技术进行快速重构。 起初它看起来很复杂,但请相信我,一旦Rx你永远不会回去。
答案 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这样的其他类可能会做同样的事情。只需提交一个带有响应功能的请求,然后在服务中进行线程处理即可。