是否可以使AsyncTask.doInBackground
同步 - 或以其他方式获得相同的结果?
class SynchronizedTask extends AsyncTask {
@Override
protected synchronized Integer doInBackground(Object... params) {
// do something that needs to be completed
// before another doInBackground can be called
}
}
就我而言,任何AsyncTask.execute()
都可以在前一个完成之前启动,但我需要在上一个任务完成后才在doInBackground
中执行代码。
编辑:正确指出,同步仅适用于同一对象实例。
遗憾的是,无法在AsyncTask
{{3}的“线程规则”部分中指定的同一对象实例上创建execute()
并多次调用AsyncTask
}。
解决方案是使用自定义documentation来序列化任务,或者,如果您使用API 11或更高版本,则Executor,如下面的评论所示。
我发布了AsyncTask.executeOnExecutor()
,显示了SerialExecutor
的实现,可用于对将按顺序执行的任务进行排队。
答案 0 :(得分:16)
理想情况下,我希望能够将AsyncTask.executeOnExecutor()
与SERIAL_EXECUTOR
一起使用,但这仅适用于API等级11或以上:
new AsyncTask().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, params);
为了定位11级以下的Android API,我最终实现了一个自定义类,它封装了一个ExecutorService
,其线程池大小为1.完整代码是开源的here。
Executors.newFixedThreadPool(int nThreads)
创建一个线程池,该线程池重用在共享的无界队列中运行的固定数量的线程。在任何时候,最多nThreads
个线程将是活动的处理任务。就我而言,nThreads
为1,这意味着任务可以排队,但在任何给定时间只执行一项任务。
以下是代码:
public abstract class SerialExecutor {
private final ExecutorService mExecutorService;
public SerialExecutor() {
mExecutorService = Executors.newFixedThreadPool(1);
}
public void queue(Context context, TaskParams params) {
mExecutorService.submit(new SerialTask(context, params));
}
public void stop() {
mExecutorService.shutdown();
}
public abstract void execute(TaskParams params);
public static abstract class TaskParams { }
private class SerialTask implements Runnable {
private final Context mContext;
private final TaskParams mParams;
public SerialTask(Context context, TaskParams params) {
mContext = context;
mParams = params;
}
public void run() {
execute(mParams);
Activity a = (Activity) mContext;
a.runOnUiThread(new OnPostExecute());
}
}
/**
* Used to notify the UI thread
*/
private class OnPostExecute implements Runnable {
public void run() {
}
}
}
这可以扩展并用作Activity
:
public class MyActivity extends Activity {
private MySerialExecutor mSerialExecutor;
@Override
public void onCreate(Bundle savedInstanceState) {
// ...
mSerialExecutor = new MySerialExecutor();
}
@Override
protected void onDestroy() {
if (mSerialExecutor != null) {
mSerialExecutor.stop();
}
super.onDestroy();
}
public void onTrigger(int param) {
mSerialExecutor.queue(this, new MySerialExecutor.MyParams(param));
}
private static class MySerialExecutor extends SerialExecutor {
public MySerialExecutor() {
super();
}
@Override
public void execute(TaskParams params) {
MyParams myParams = (MyParams) params;
// do something...
}
public static class MyParams extends TaskParams {
// ... params definition
public MyParams(int param) {
// ... params init
}
}
}
}
答案 1 :(得分:3)
您可能需要考虑使用IntentService。看起来它可能更适合您的流程,因为它内置了排队功能。
答案 2 :(得分:0)
public class RestAsyncTask1 extends AsyncTask<String, Void, String> {
private AsyncTaskCompleteListener callback;
private Context context;
private String method;
private static final AtomicInteger PROGRESS_NUM = new AtomicInteger(0);
private static ProgressDialog PROGRESS_DIALOG;
public RestAsyncTask1(Context context, AsyncTaskCompleteListener callback, String method) {
this.callback = callback;
this.context = context;
this.method = method;
}
public static String format(String url, String... params) {
String[] encoded = new String[params.length];
for (int i = 0; i < params.length; i++) {
encoded[i] = Uri.encode(params[i]);
}
return String.format(url, (String[]) encoded);
}
@Override
protected void onPreExecute() {
int x = PROGRESS_NUM.getAndIncrement();
if (x == 0) {
String title = "M_yug";
PROGRESS_DIALOG = new ProgressDialog(context);
// PROGRESS_DIALOG.setTitle(title);
PROGRESS_DIALOG.setIndeterminate(true);
PROGRESS_DIALOG.setCancelable(false);
PROGRESS_DIALOG.setOnCancelListener(null);
PROGRESS_DIALOG.setMessage("Loading. Please wait...");
PROGRESS_DIALOG.show();
}
}
@Override
protected String doInBackground(String... params) {
String url = params[0];
String response = null;
HttpURLConnection connection = null;
if (params.length > 1) {
if (method.equals(Method.GET)) {
url = format(url, (String[]) Arrays.copyOfRange(params, 1, params.length));
} else if (params.length > 2) {
url = format(url, (String[]) Arrays.copyOfRange(params, 1, params.length - 1));
}
try {
URL call = new URL(url);
connection = (HttpURLConnection) call.openConnection();
connection.setRequestProperty("Content-Type", "application/json");
//connection.setRequestProperty("M-Yug", Utilities.VERSION);
connection.setRequestMethod(method);
connection.setDoOutput(true);
if (method.equals("POST")) {
BufferedOutputStream outputStream = new BufferedOutputStream(connection.getOutputStream());
outputStream.write(params[params.length - 1].getBytes());
outputStream.flush();
}
int status = connection.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
InputStream is = connection.getInputStream();
response = readValue(is);
} else if (status == 400) {
InputStream is = connection.getErrorStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
reader.close();
Toast.makeText(context, "" + builder.toString(), Toast.LENGTH_SHORT).show();
}
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
return response;
}
@Override
protected void onPostExecute(String s) {
int x = PROGRESS_NUM.decrementAndGet();
if (x == 0 && PROGRESS_DIALOG != null && PROGRESS_DIALOG.isShowing()) {
PROGRESS_DIALOG.dismiss();
}
if (s!=null) {
String resopnse=s.toString();
callback.onSuccess(resopnse);
} else {
Toast.makeText(context,"Server Not Responding",Toast.LENGTH_SHORT).show();
}
}
private String readValue(InputStream is) {
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
String line;
try {
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (Exception e) {
}
return sb.toString();
}
enum Method {
GET, POST
}
}
答案 3 :(得分:-2)
AsyncTask用于运行后台线程,以便您不会中断当前进程。
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
首先调用doInBackground函数,返回的对象将在post执行后移动到。 你希望在一些进程之后运行哪一行代码,你可以把它放在PostExecute函数中。 这肯定会帮助你