I created an asynctask and in its doInBackground() method i started a thread like this:
private class myAsyntask extends Asynctask{
doInBackground(){
Thread t = new Thread(new Runnable(){
public void run()
{
while(someBoolean!=true){
Thread.currentThread.sleep(100);
}
}
});
}
onPostExecute(){
//do something related to that variable
}
}
problem I am facing is after 1st iteration of Thread.sleep() , onPostExecute() is called , instead I thought that asynctask will run this thread on background and when that boolean is true onPostexecute() is called.I am not able to understand why this happens ?
AsyncTask automatically creates a new Thread for you, so everything you do in doInBackground() is on another thread.
What you are doing is this:
AsyncTask creates a new Thread and runs doInBackground().
a new Thread (t) is created from the AsyncTask-Thread.
doInBackground() is completed, as all it does is create the Thread t and thus jumps to onPostExecute().
Thread t would still be running in the background (however, you do not call start() on t, meaning that it is not started).
Instead you want your doInBackground() method to look something like this:
doInBackground(){
while(someBoolean!=true){
//Perform some repeating action.
Thread.sleep(100);
}
}
First of all, in your code you don't even start thread t, so all that happens in doInBackground is creation of new thread and then moving on to onPostExecute().
Secondly, you don't even need separate thread, since doInBackground() handles this for you, so you can just use something like
doInBackground(){
while(someBoolean!=true){
Thread.currentThread.sleep(100);
}
}
if you wish, however, to stick with separate thread, you can start thread and wait for it's completion by using .join(); like
doInBackground(){
Thread t = new Thread(new Runnable(){
public void run() {
while(someBoolean!=true){
Thread.currentThread.sleep(100);
}
}
});
t.start();
t.join();
}
onPostExecute can only be called when doInBackground has return-ed. In your code, the only possible way this can happen is sleep throwing an Exception (InterruptedException??)
Related
I am invoking a method:
method = (MessageController.getInstance()).getClass().getMethod(data.getString("action") + "Action", cArg);
method.invoke(MessageController.getInstance(), "param1");
and the method:
public static void errorAction(String data){
ProgressDialog dialog = new ProgressDialog(context);
dialog.setTitle("hi");
dialog.setMessage("there");
dialog.show();
}
However i get the following exception:
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
on the dialog.show() part.
Is this because of invoking actually happens on a new thread?
If yes, how to make it run on UI thread? How to just show the dialog?
Thanks!
I'm not exactly sure why you're using reflection to do this, but yes. The reason is you're not on a Looper when invoking the show() method. More likely, you'll get another error if it isn't on the main looper thread (UI thread).
Handlers and Loopers go hand-in-hand. A Looper keeps a thread alive and running and a Handler executes Runnables and posts Messages on that thread.
So, to post to a main thread, you can create a new Handler yourself and pass in the main Looper which will ensure it gets executed on the main thread:
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// Code to execute on the main thread.
}
}
Doing it this way doesn't require an Activity or View. It will always post on the UI thread and not another Looper thread that you created. Note that this asynchronous and won't execute until the next draw pass.
Or you can run it in the UI thread, like so:
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
method = (MessageController.getInstance()).getClass().getMethod(data.getString("action") + "Action", cArg);
method.invoke(MessageController.getInstance(), "param1");
}
});
The following were supposed to be the same if I am not mistaking.
Using AsyncTask:
private class GetDataTask extends AsyncTask<String, Void, String>{
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(String... params) {
return NetConnection.getRecordData(mUserId, mUserPassword);
}
#Override
protected void onPostExecute(String result) {
parseJson(result);
}
}
Using a Thread:
new Thread( new Runnable() {
#Override
public void run() {
String res = NetConnection. getRecordData(mUserId, mUserPassword);
parseJson(res);
}
}).start();
But when uploading a file, the AsyncTask runs synchronously while the Thread run asynchronously(in parallel).
Why is so? Why AsyncTask behaves like this? Isn't AsyncTask supposed to run asynchronously?
I am little confused so I need your help.
This is how I invoke the GetDataTask:
new GetDataTask().execute()
I prefer using AsyncTask but it is not doing the job for me. Please refer to my early question for more details
As of 4.x calling 2 AsyncTasks will cause them to be executed serially.
One way to fix this is using the following code
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) {
myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
else {
myTask.execute();
}
You can read more at: http://commonsware.com/blog/2012/04/20/asynctask-threading-regression-confirmed.html
Ok following are the notes from the official java doc...
Order of execution
When first introduced, AsyncTasks were executed serially on a single
background thread. Starting with DONUT, this was changed to a pool of
threads allowing multiple tasks to operate in parallel. Starting with
HONEYCOMB, tasks are executed on a single thread to avoid common
application errors caused by parallel execution.
If you truly want parallel execution, you can invoke
executeOnExecutor(java.util.concurrent.Executor, Object[]) with THREAD_POOL_EXECUTOR.
SO if you invoke two AsyncTask together.. they would not be executed in parallel (exception is donut, encliar and gingerbread)... You can use executeOnExecutor to execute them in parallel...
From your code we can see you have called parseJson(result); in onPostExecute() of AsyncTask which runs in MainUIThread of Applications. So at that point your code runs Synchronously..
Put parseJson(result); method in doInBackGround() Which runs only in other worker thread.
While you have called same thing in Thread. So both
String res = NetConnection. getRecordData(mUserId, mUserPassword);
parseJson(res);
Runs in other worker thread out of MAinUiThread on which you experienced Asynchronously.
Note:
But be sure your parseJson(res); doesn't update UI while it is in doInBackground().
Looks like that actual problem is not in file uploading but in parseJson method.
In your Thread example you parsing Json in separate thread while in AsyncTask case you parsing Json in UI thread.
I am developing an application using Android SDK. In this application I am facing a problem when an Activity starts a Thread. The new Thread starts an AsyncTask, but the Thread has to wait for completion of the AsyncTask execution.
Is it possible to start AsyncTask in a thread, and if so, how should it be implement?
Please can anyone share your experience with me about this kind of tasks.
Thanks in advance
You should not create an AsyncTask from a thread other than main thread.
If you should wait anyway, why create AsyncTask? perform it on the thread.
just say thread to sleep for some times and then check a variable again like this
in below code someValue was setted in asynctask postExecute method
new Thread(new Runnable(){
#Override
public void run(){
while(!someValue) {
try {
Thread.sleep(200);
} catch {
Log.i("LOG", "ERROR");
}
}
Log.i("LOG", "Async Task Finished");
}
}).start();
I have a gui thread starting a new thread to do some busy things. The GUI thread will wait the worker thread to be completed, in the mean time the GUI need to be responsive.
Psedo code:
main thread:
start_thread();
wait_thread_done();
work thread:
doing_sth();
notify_main_thread();
What is the easiest way to do this in android?
The easiest way to do this is with Android's AsyncTask. The documentation is here
http://developer.android.com/reference/android/os/AsyncTask.html
And you can call Activity.runOnUiThread() to update the UI from your background task.
A small working snippet :
new Thread() {
public void run() {
handler.post(new Runnable() {
public void run() {
try{
// **Do the GUI work here**
} catch (Exception e) { }
}});
};
}.start();
Call Activity#runOnUiThread(Runnable), the Runnable you pass to that method will execute on the GUI thread.
Or use an AsyncTask - which is the proper way to do it.
waiting for result will make gui thread unresponsive. you need to use AsyncTask and override onPostExecute to perform operation required when background thread is done
I want to update my UI from a Thread which updates a Progressbar. Unfortunately, when updating the progressbar's drawable from the "runnable" the progressbar disappears!
Changing the progressbars's drawable in onCreate() on the otherside works!
Any Suggestions?
public void onCreate(Bundle savedInstanceState) {
res = getResources();
super.onCreate(savedInstanceState);
setContentView(R.layout.gameone);
pB.setProgressDrawable(getResources().getDrawable(R.drawable.green)); //**Works**/
handler.postDelayed(runnable, 1);
}
private Runnable runnable = new Runnable() {
public void run() {
runOnUiThread(new Runnable() {
public void run()
{
//* The Complete ProgressBar does not appear**/
pB.setProgressDrawable(getResources().getDrawable(R.drawable.green));
}
});
}
}
You should do this with the help of AsyncTask (an intelligent backround thread) and ProgressDialog
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread. An asynchronous task is defined by 3 generic types, called Params, Progress and Result, and 4 steps, called begin, doInBackground, processProgress and end.
The 4 steps
When an asynchronous task is executed, the task goes through 4 steps:
onPreExecute(), invoked on the UI thread immediately after the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.
onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
Threading rules
There are a few threading rules that must be followed for this class to work properly:
The task instance must be created on the UI thread.
execute(Params...) must be invoked on the UI thread.
Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually.
The task can be executed only once (an exception will be thrown if a second execution is attempted.)
Example code
What the adapter does in this example is not important, more important to understand that you need to use AsyncTask to display a dialog for the progress.
private class PrepareAdapter1 extends AsyncTask<Void,Void,ContactsListCursorAdapter > {
ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(viewContacts.this);
dialog.setMessage(getString(R.string.please_wait_while_loading));
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
/* (non-Javadoc)
* #see android.os.AsyncTask#doInBackground(Params[])
*/
#Override
protected ContactsListCursorAdapter doInBackground(Void... params) {
cur1 = objItem.getContacts();
startManagingCursor(cur1);
adapter1 = new ContactsListCursorAdapter (viewContacts.this,
R.layout.contact_for_listitem, cur1, new String[] {}, new int[] {});
return adapter1;
}
protected void onPostExecute(ContactsListCursorAdapter result) {
list.setAdapter(result);
dialog.dismiss();
}
}
The most simplest solution I have seen to supply a short
execution to the UI thread is via the post() method of a view.
This is needed since UI methods are not re-entrant. The
method for this is:
package android.view;
public class View;
public boolean post(Runnable action);
The post() method corresponds to the SwingUtilities.invokeLater().
Unfortunately I didn't find something simple that corresponds to
the SwingUtilities.invokeAndWait(), but one can build the later
based on the former with a monitor and a flag.
So what you save by this is creating a handler. You simply need
to find your view and then post on it. You can find your view via
findViewById() if you tend to work with id-ed resources. The resulting
code is very simple:
/* inside your non-UI thread */
view.post(new Runnable() {
public void run() {
/* the desired UI update */
}
});
}
Note: Compared to SwingUtilities.invokeLater() the method
View.post() does return a boolean, indicating whether the
view has an associated event queue. Since I used the
invokeLater() resp. post() anyway only for fire and forget,
I did not check the result value. Basically you should
call post() only after onAttachedToWindow() has been called
on the view.
Best Regards
If you use Handler (I see you do and hopefully you created its instance on the UI thread), then don't use runOnUiThread() inside of your runnable. runOnUiThread() is used when you do smth from a non-UI thread, however Handler will already execute your runnable on UI thread.
Try to do smth like this:
private Handler mHandler = new Handler();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gameone);
res = getResources();
// pB.setProgressDrawable(getResources().getDrawable(R.drawable.green)); **//Works**
mHandler.postDelayed(runnable, 1);
}
private Runnable runnable = new Runnable() {
public void run() {
pB.setProgressDrawable(getResources().getDrawable(R.drawable.green));
pB.invalidate(); // maybe this will even not needed - try to comment out
}
};
Use the AsyncTask class (instead of Runnable). It has a method called onProgressUpdate which can affect the UI (it's invoked in the UI thread).
You need to create a Handler in the UI thread and then use it to post or send a message from your other thread to update the UI
If you don't like the AsyncTask you could use the observer pattern. In that example use the ResponseHandler as an inner class in your activity then have a string message that will set the progress bars percentage... You would need to make sure that any alterations to the UI are performed within the ResponseHandler to avoid freezing up the UI, then your worker thread (EventSource in the example) can perform the tasks required.
I would use the AsyncTask tho, however the observer pattern can be good for customization reasons, plus its easier to understand. Also im not sure if this way is widely accepted or will 100% work. Im downloading and the android plugin now to test it
As recommended by official documentation, you can use AsyncTask to handle work items shorter than 5ms in duration. If your task take more time, lookout for other alternatives.
HandlerThread is one alternative to Thread or AsyncTask. If you need to update UI from HandlerThread, post a message on UI Thread Looper and UI Thread Handler can handle UI updates.
Example code:
Android: Toast in a thread