I want to ask user for some details while doing some work in doInBackground() of AsyncTask (showing to user some dialog with choices in UI-thread), and after users choice continue the job in doInBackground() with chosen parameters from dialog.
What is a best mechanism of transfer this parameter to doInBackground()? How I should pause (and continue) thread doing doInBackground() (maybe object.wait() and notify()?)? Should I use a Handler for this purpose?
I would ask user for input before actually starting background task. If this is not possible there are couple possibilities:
You can use lock object and do usual wait()/notify() stuff on it. You still need to pass data from UI thread to your background thread though
I would use queue to pass data from UI thread to background thread and let it handle all the locking.
Something like this (kind of pseudo-code)
class BackgroundTask extends AsyncTask<BlockingQueue<String>, ...> {
void doInBackground(BlockingQueue<String> queue) {
...
String userInput = queue.take(); // will block if queue is empty
...
}
}
// Somewhere on UI thread:
BlockingQueue<String> queue = new ArrayBlockingQueue<String>(1);
BackgroundTask task = new BackgroundTask<BlockingQueue<String>,....>();
task.execute(queue);
....
....
String userInput = edit.getText().toString(); // reading user input
queue.put(userInput); // sending it to background thread. If thread is blocked it will continue execution
You can use a Callable, submit it to an Executor, the Executor will return FutureTask then you will wait in a while loop until FutureTask.isDone == true;
This here is an example http://programmingexamples.wikidot.com/futuretask
I hope my answer will solve your problem surely.
//DO ALL BELOW CODE IN doInBackground() method of AsyncTask
String userInput="";
YouActivity.this.runOnUiThread(new Runnable() {
public void run() {
//SHOW YOUR DIALOG HERE
}
});
while("".equals(userInput))
{
YouActivity.this.runOnUiThread(new Runnable() {
public void run() {
userInput=editText.getText().toString();//fetching user input from edit Text
}
});
}
Thanks :)
Related
OK, so I know how to do a backround task, I know how to do a periodic task (using handle postdelayed and runnable), I also know how to do UI task from background thread (via handler) but I am not able to execute a periodic background task that does some action on the UI thread.
I am trying to execute some background task every minute in which I have to make a network call. After the call is over, depending on the output I have to update the UI. I tried to do something like this
private void DoTask() {
Thread thread = new Thread() {
public void run() {
Looper.prepare();
final Handler handler = new Handler();
handler.post(netRunnable);
Looper.loop();
}
};
thread.start();
}
Runnable netRunnable = new Runnable() {
#Override
public void run() {
handler.getLooper().prepare();
final Handler handler1 = new Handler(Looper.getMainLooper());
if ( do background work and check result){
handler1.post(new Runnable() {
#Override
public void run() {
//Do UI Task
}
});
}
handler.getLooper().loop();
handler.postDelayed(netRunnable, 60000);
}
}
I understand that there might be some fundamental flaws with my implementation but I do not know how to do this task properly. Right now it is giving the error that Only one Looper may be created per thread.I get what it is trying to say. But can anyone please suggest to do this the right way.
You could use Async Tasks. These are designed for it :
http://developer.android.com/reference/android/os/AsyncTask.html
It allows you to execute a network call in the background, then when you get the result, execute an action on the UI thread
Declaration :
private class MyTask extends AsyncTask<Input, Void, Output> {
protected Output doInBackground(Input... inputs) {
// do something on the network
return myOutput;// use this to transmit your result
}
protected void onPostExecute(Output result) {
// do something on UI thread with the result
}
}
If you want to repeat it, just create a runnable to launch it, and after every call, schedule the next one :
MyTask myTask;
Handler handler = new Handler();
Runnable myRunnable = new Runnable() {
#Override
public void run() {
MyTask myTask = new MyTask();
myTask.execute(myArg);
handler.postDelayed(netRunnable, 60000); // schedule next call
}
}
To launch it for the first time :
handler.postDelayed(myRunnable, 60000);
Or, if you want to launch it immediately :
handler.post(myRunnable);
Do not forget to cancel the Task when your activity is destroyed :
myTask.cancel(true);
Maybe you are better of, creating a seperate (Intent)Service and calling it periodically with postDelayed. Create a BroadcastReceiver in your Activity and handle UI changes there.
Another hint for handling UI changes from other threads: It is not possible. Therefore you need to call runOnUiThread. Here is how to use it
If activities are frequently switching, why not reversing the responsibilities. You might create a service which executes a periodic network task.
Then,
- either your activities periodically call this service to get the value.
- or you use a listener system : you create an interface that your activities must implement in order to get notified from the task completion
onCreate(Bundle savedInstanceState){
// show dialog A if something is not correct
new Thread(){
public void run(){
if(something is wrong) {
runOnUIThread(new Runnable(){
public void run(){
showDialog(A);
}
});
}
}
}.start();
// show dialog B
showDialog(B);
}
I want to know
which dialog will be shown first, and is the order indeterminate? why?
if the order is indeterminate, how can i reproduce the case that A is shown before B?
Thanks!
Which dialog will be shown first is not defined and you should not rely on one occurring before the other as above. The thread scheduler is not identically deterministic in all situations.
You need to lock on a mutex (or any other locking device) to make sure one is shown before the other.
Your question about which dialog will show first is indeterminate. There are cases where the order will flip flop. But generally B would be shown first since 9/10 it will get to place it's event on the UI thread before your thread could detect there was a problem.
I'd suggest using AsyncTask to perform whatever mechanisms are needed to startup, then in the onPostExecute() allow your program to resume starting up so it can showDialog(B) for whatever it needs. That way if dialog A is showing you can stop the startup process there and not show b.
public class MyAsyncStartup extends AsyncTask<Integer,Integer,MyResult> {
MyActivity activity;
public MyResult handleBackground() {
if( somethingWentWrong ) return null;
}
public onPostExecute( MyResult result ) {
if( result == null ) {
showDialog(B);
} else {
activity.resumeStartupAndShowA();
}
}
}
I don't think it is possible that A is shown before B... this is because runOnUIThread adds the event TO THE END of the event queue. The code in that event (showing dialog A) is not going to get executed until after the onCreate() finishes (which means that dialog B gets shown first).
What cannot be guaranteed is the order between showing dialog B and calling runOnUIThread, but that doesn't matter. Here is a fragment from the official docs:
[runOnUIThread] Runs the specified action on the UI thread. If the current thread is the UI thread, then the action is executed immediately. If the current thread is not the UI thread, the action is posted to the event queue of the UI thread.
N/A
You can't show B until you know whether or not A will be shown. So you have to wait for the worker thread no matter what. Would it be possible to put showDialog(B) in your other thread like this?
onCreate(Bundle savedInstanceState){
// show dialog A if something is not correct
new Thread(){
public void run(){
runOnUiThread(new Runnable(){
public void run(){
if(something is wrong) {
showDialog(A);
}
showDialog(B);
}
});
}
}
}.start();
}
hi all
since i am using a button and on the click of that button it connects to a Web Service.
But the problem is that when i press the button it does not showed me that it has been clicked and goes to connect to the internet and web service. after connecting it shows me the response that it has been clicked. in short the response of button is very slow. if that buton has some INternet connectvity in its Listener.
i know it has something to do with UI thread. but please friends guide me through this.
Thanks a bunch,
Put the following code in your class:
// Need handler for callbacks to UI Threads
// For background operations
final Handler mHandler = new Handler();
// Create Runnable for posting results
final Runnable mUpdateResults = new Runnable() {
public void run() {
// Do your task which needs to get done after webservice call is complete.
}
};
And for calling the webservice use the following code in button event:
new Thread() {
public void run() {
// Place the webservice call here.
mHandler.post(mUpdateResults);
}
}.start();
Actually what are you looking for is multithreading, all the webservice calls and network activities should go in separate thread.
After the thread start() call you can do what ever you want and would be done instantly without any delay (in your case showing that button pressed).
You have to use Handler for this background operation already ask on OS follow this link
progress dialog not showing in android?
You should write a class say MyWebService and extend it from AsyncTask. Perform the connect operation in its overridden doInBackground() method and update any UI changes in its onPostExecute() method.
Create a new Thread in the onClickListener that does the heavy work in the background. That way the UI thread will be able to update the state of the button:
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
new Thread(new Runnable() {
#Override
public void run() {
// Code that connects to web service goes here...
}
}).start();
});
In my OnCreate method I have created a thread that listens to incoming message!
In OnCreate() {
//Some code
myThread = new Thread() {
#Override
public void run() {
receiveMyMessages();
}
};
myThread.start();
// Some code related to sending out by pressing button etc.
}
Then, receiveMyMessage() functions…
Public void receiveMyMessage()
{
//Receive the message and put it in String str;
str = receivedAllTheMessage();
// << here I want to be able to update this str to a textView. But, How?
}
I checked this article but it did not work for me, no luck!
Any updates to the UI in an Android application must happen in the UI thread. If you spawn a thread to do work in the background you must marshal the results back to the UI thread before you touch a View. You can use the Handler class to perform the marshaling:
public class TestActivity extends Activity {
// Handler gets created on the UI-thread
private Handler mHandler = new Handler();
// This gets executed in a non-UI thread:
public void receiveMyMessage() {
final String str = receivedAllTheMessage();
mHandler.post(new Runnable() {
#Override
public void run() {
// This gets executed on the UI thread so it can safely modify Views
mTextView.setText(str);
}
});
}
The AsyncTask class simplifies a lot of the details for you and is also something you could look into. For example, I believe it provides you with a thread pool to help mitigate some of the cost associated with spawning a new thread each time you want to do background work.
Android supports message-passing concurrency using handlers and sendMessage(msg). (It is also possible to use handlers for shared-memory concurrency.) One tip is to call thread.setDaemon(true) if you wish the thread to die when the app dies. The other tip is to have only one handler and use message.what and a switch statement in the message handler to route messages.
Code and Code
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