Can An Android Asynctask Doinbackground Be Synchronized To Serialize The Task Execution?
Solution 1:
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:
newAsyncTask().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:
publicabstractclassSerialExecutor {
privatefinal ExecutorService mExecutorService;
publicSerialExecutor() {
mExecutorService = Executors.newFixedThreadPool(1);
}
publicvoidqueue(Context context, TaskParams params) {
mExecutorService.submit(newSerialTask(context, params));
}
publicvoidstop() {
mExecutorService.shutdown();
}
publicabstractvoidexecute(TaskParams params);
publicstaticabstractclassTaskParams { }
privateclassSerialTaskimplementsRunnable {
privatefinal Context mContext;
privatefinal TaskParams mParams;
publicSerialTask(Context context, TaskParams params) {
mContext = context;
mParams = params;
}
publicvoidrun() {
execute(mParams);
Activitya= (Activity) mContext;
a.runOnUiThread(newOnPostExecute());
}
}
/**
* Used to notify the UI thread
*/privateclassOnPostExecuteimplementsRunnable {
publicvoidrun() {
}
}
}
This can be extended and used as a serial task executor in an Activity
:
publicclassMyActivityextendsActivity {
private MySerialExecutor mSerialExecutor;
@OverridepublicvoidonCreate(Bundle savedInstanceState) {
// ...
mSerialExecutor = newMySerialExecutor();
}
@OverrideprotectedvoidonDestroy() {
if (mSerialExecutor != null) {
mSerialExecutor.stop();
}
super.onDestroy();
}
publicvoidonTrigger(int param) {
mSerialExecutor.queue(this, newMySerialExecutor.MyParams(param));
}
privatestaticclassMySerialExecutorextendsSerialExecutor {
publicMySerialExecutor() {
super();
}
@Overridepublicvoidexecute(TaskParams params) {
MyParamsmyParams= (MyParams) params;
// do something...
}
publicstaticclassMyParamsextendsTaskParams {
// ... params definitionpublicMyParams(int param) {
// ... params init
}
}
}
}
Solution 2:
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.
Solution 3:
publicclassRestAsyncTask1extendsAsyncTask<String, Void, String> {
private AsyncTaskCompleteListener callback;
private Context context;
private String method;
privatestaticfinalAtomicIntegerPROGRESS_NUM=newAtomicInteger(0);
privatestatic ProgressDialog PROGRESS_DIALOG;
publicRestAsyncTask1(Context context, AsyncTaskCompleteListener callback, String method) {
this.callback = callback;
this.context = context;
this.method = method;
}
publicstatic String format(String url, String... params) {
String[] encoded = newString[params.length];
for (inti=0; i < params.length; i++) {
encoded[i] = Uri.encode(params[i]);
}
return String.format(url, (String[]) encoded);
}
@OverrideprotectedvoidonPreExecute() {
intx= PROGRESS_NUM.getAndIncrement();
if (x == 0) {
Stringtitle="M_yug";
PROGRESS_DIALOG = newProgressDialog(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();
}
}
@Overrideprotected String doInBackground(String... params) {
Stringurl= params[0];
Stringresponse=null;
HttpURLConnectionconnection=null;
if (params.length > 1) {
if (method.equals(Method.GET)) {
url = format(url, (String[]) Arrays.copyOfRange(params, 1, params.length));
} elseif (params.length > 2) {
url = format(url, (String[]) Arrays.copyOfRange(params, 1, params.length - 1));
}
try {
URLcall=newURL(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")) {
BufferedOutputStreamoutputStream=newBufferedOutputStream(connection.getOutputStream());
outputStream.write(params[params.length - 1].getBytes());
outputStream.flush();
}
intstatus= connection.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
InputStreamis= connection.getInputStream();
response = readValue(is);
} elseif (status == 400) {
InputStreamis= connection.getErrorStream();
BufferedReaderreader=newBufferedReader(newInputStreamReader(is));
StringBuilderbuilder=newStringBuilder();
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;
}
@OverrideprotectedvoidonPostExecute(String s) {
intx= 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) {
BufferedReaderbr=null;
StringBuildersb=newStringBuilder();
String line;
try {
br = newBufferedReader(newInputStreamReader(is));
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (Exception e) {
}
return sb.toString();
}
enumMethod {
GET, POST
}
}
Solution 4:
AsyncTask is used to run a background thread so that you current process is not interupted .
privateclassDownloadFilesTaskextendsAsyncTask<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;
}
protectedvoidonProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protectedvoidonPostExecute(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
Post a Comment for "Can An Android Asynctask Doinbackground Be Synchronized To Serialize The Task Execution?"