Can I synchronize Android AsyncTask doInBackground to serialize task execution?

Is it possible to synchronize AsyncTask.doInBackground- or to achieve the same result in a different way?

class SynchronizedTask extends AsyncTask {

    @Override
    protected synchronized Integer doInBackground(Object... params) {
        // do something that needs to be completed 
        // before another doInBackground can be called
    }
}

In my case, anyone AsyncTask.execute()can be started before the previous one is finished, but I need to execute the code in doInBackgroundonly after the previous task has completed.

EDIT . As correctly indicated, synchronization works with only one instance of an object. Unfortunately, it is impossible to create AsyncTaskand call execute()more than once in one instance of an object, as indicated in the "Threading Rules" section of the AsyncTask documentation .

The solution is to use a custom Executor to serialize tasks, or if you are using API 11 or higher AsyncTask.executeOnExecutor(), as suggested in the comments below.

I posted a response that shows an implementation SerialExecutorthat can be used to queue tasks that will be executed sequentially.

+5
source share
4 answers

Ideally, I would like to use AsyncTask.executeOnExecutor()with SERIAL_EXECUTOR, but this is only available for API level 11 or higher:

new AsyncTask().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, params);

Android- Android 11, , ExecutorService 1. .

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
            }
        }
    }
}
+15

, IntentService. , , .

+3
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
    }
}
0

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");
 }

}

where, first of all, the doInBackground function will be activated, and the returned object will be moved to post-execution. which line of code you want to run after some process that you can put in the PostExecute function. it will definitely help you

-2
source

All Articles