Can an Android AsyncTask doInBackground be synchronized to serialize the task execution?

前端 未结 4 553
滥情空心
滥情空心 2020-12-03 12:06

Is it possible to make AsyncTask.doInBackground synchronized - or achieve the same result in another way?



        
相关标签:
4条回答
  • 2020-12-03 12:18
    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 讨论(0)
  • 2020-12-03 12:21

    Ideally, I'd like to be able to use AsyncTask.executeOnExecutor() with a SERIAL_EXECUTOR, but this is only available for API level 11 or above:

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

    To target the Android APIs below level 11, I ended up implementing a custom class which encapsulates an ExecutorService with a thread pool size of 1. The full code is open-sourced here.

    Executors.newFixedThreadPool(int nThreads) creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue. At any point, at most nThreads threads will be active processing tasks. In my case, nThreads is 1, which means tasks can be queued, but only one task will be executed at any given time.

    Here is the code:

    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() {
    
            }
        }
    }
    

    This can be extended and used as a serial task executor in an 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
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-03 12:23

    You may want to think about using IntentService instead. It seems like it may be a better fit for your process since it has built in features for queuing.

    0 讨论(0)
  • 2020-12-03 12:31

    AsyncTask is used to run a background thread so that you current process is not interupted .

    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 your doInBackground function iscalled and the returned object will move to on post execute. which line of code you want to run after some process you can put that in PostExecute function. this will surely help you

    0 讨论(0)
提交回复
热议问题