Reputation: 14847
Ok, it's my first time with Async and Queue in Java so the code might not be the best... anyway:
I want to write an AsyncTask which run an HTTP request, and if the users sends more requests while Async is running, it adds the request to the Queue and then the async execute every request.
private Queue<String> pasteQueue = new LinkedList<String>();
private boolean running = false;
I have created this method to manage every request:
public void postPaste(String title, String code, String language, String scadenza, int visibility)
{
String dev_key = "";
StringBuilder url = new StringBuilder();
url.append("http://pastebin.com/api/api_post.php?api_option=paste")
.append("&api_paste_private=").append(visibility)
.append("&api_paste_name=").append(title)
.append("&api_paste_expire_date=").append(scadenza)
.append("&api_paste_format=").append(language)
.append("&api_dev_key=").append(dev_key)
.append("&api_paste_code=").append(code);
Log.d(MyActivity.DEBUG_TAG, "URL: " + url.toString());
// Todo: implement api_user_key
Log.d(MyActivity.DEBUG_TAG, "running == " + running);
if (running)
{
Log.d(MyActivity.DEBUG_TAG, "PASTE added to queue");
pasteQueue.add(url.toString());
}
else
{
Log.d(MyActivity.DEBUG_TAG, "Execute async");
execute(url.toString());
}
}
To check if the async is running, i created a boolean variable (running), its set to "true" when doInBackground is called and to false when onPostExecute finish.
It's my doInBackground method:
@Override
protected String doInBackground(String... params) {
Log.d(MyActivity.DEBUG_TAG, "doInBackground");
if (params[0] == null)
{
return null;
}
running = true;
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response;
String finalResponse = null;
try
{
response = httpClient.execute(new HttpGet(params[0]));
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() == HttpStatus.SC_OK)
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
response.getEntity().writeTo(outputStream);
outputStream.close();
finalResponse = outputStream.toString();
}
else
{
response.getEntity().getContent().close();
}
} catch (ClientProtocolException e) {
// ToDo: Something
} catch (IOException e) {
// ToDo: Something
}
return finalResponse; //To change body of implemented methods use File | Settings | File Templates.
}
First, i check if params[0] is null (in case pasteQueue.poll() return null) then i run a simple http request..
I put the full doInBackground because the problem might be in the HTTP request (i never used HTTP functions in Android, yup i'm new to Android in general.)
Then, the onPosteExecute is only this:
@Override
protected void onPosteExecute(String s)
{
Log.d(MyActivity.DEBUG_TAG, "onPostExecute");
super.onPostExecute(s); //To change body of overridden methods use File | Settings | File Templates.
if (pasteQueue.size() > 0)
{
Log.d(MyActivity.DEBUG_TAG, "queue.size > 0, poll item");
execute(pasteQueue.poll());
}
running = false;
Log.d(MyActivity.DEBUG_TAG, "onPostExecute - fine");
}
(I removed useless code)
I used a button which run postPaste and, if i press the button again (onPostExecute called) the application crash with this:
Caused by: java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)
11-30 18:06:50.608: ERROR/AndroidRuntime(2246): FATAL EXCEPTION: main java.lang.IllegalStateException: Could not execute method of the activity at android.view.View$1.onClick(View.java:3599) at android.view.View.performClick(View.java:4204) at android.view.View$PerformClick.run(View.java:17355) at android.os.Handler.handleCallback(Handler.java:725) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:5041) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at android.view.View$1.onClick(View.java:3594) ... 11 more Caused by: java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once) at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:578) at android.os.AsyncTask.execute(AsyncTask.java:534) at com.revonline.pastebin.Pastebin.postPaste(Pastebin.java:65) at com.revonline.pastebin.MyActivity.sharePaste(MyActivity.java:132) ... 14 more
What is the problem? AsyncTask is not suitable for this situation? I should use normal threads code?
I readed a question where one said the async task might still run for 5 seconds but i don't think it's the same problem..
Upvotes: 2
Views: 6091
Reputation: 1006944
What is the problem?
You need to create a new AsyncTask
instance for each execute()
call. You cannot call execute()
twice on the same AsyncTask
instance.
AsyncTask is not suitable for this situation?
I wouldn't use it here.
I should use normal threads code?
I would use an IntentService
. It already has a background thread. It already has a queue. And it will be more reliable than an AsyncTask
in completing the work in the queue if your app moves to the background, as it is less likely that Android will terminate your process right away.
Upvotes: 2