How to execute some code in Android UI thread async? - android

I'm new to Android development. I've be working on Swing and SWT for several years. Both Swing and SWT has a stratage to execute code in UI thread sync and async. The typical usage is doing some time-consume staff in one thread then display the result in UI thread async.
So my question is, is there similiar stratage in Android? Here is my code. Parameter runnable is some time-consume code. This method will display a waiting dialog during the execution then EXPECT to show a Toast after it is finished. But the Toast need to be show in UI thread. So how to do that?
public static void showWaitingDialog(final Activity parent, final Runnable runnable, String msg) {
if (StringUtils.isEmpty(msg)) {
msg = "processing...";
}
final ProgressDialog waitingDialog = ProgressDialog.show(parent, "Please Wait...", msg, true);
// execute in a new thread instead of UI thread
ThreadPoolUtil.execute(new Runnable() {
public void run() {
try {
// some time-consume operation
runnable.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
waitingDialog.dismiss();
}
// TODO: How to display a Toast message here? execute some code in UI Thread.
}
});
}
And is there some words about Android UI system? Such as is it Thread-Safe, how thread works together and so on. Many Thanks!

There are several ways for doing that,
AsyncTask -
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. Example for using AsyncTask
Service -
A Service is an application component representing either an
application's desire to perform a longer-running operation while not
interacting with the user or to supply functionality for other
applications to use. Example for Using Service.
IntentService -
IntentService is a base class for Services that handle asynchronous
requests (expressed as Intents) on demand. Clients send requests
through startService(Intent) calls; the service is started as needed,
handles each Intent in turn using a worker thread, and stops itself
when it runs out of work. Example for using IntentService.

You can use AsyncTask like this.
To call AsyncTask
new getAsynctask().execute("");
and here is the class for geting result.
class getAsynctask extends AsyncTask<String, Long, Integer> {
protected void onPreExecute() {
super.onPreExecute();
loading = ProgressDialog.show(Pass.this, null, "Please wait...");
}
protected Integer doInBackground(String... params) {
try {
// do your coding
return null;
} catch (Exception e) {
return null;
}
}
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
try {
if (loading != null && loading.isShowing())
loading.dismiss();
} catch (Throwable t) {
Log.v("this is praki", "loading.dismiss() problem", t);
}
}
}

Whenever you are working with Separate thread which is not your UI thread the best way is to use Handler. Whenever you want to intimate user from your Thread, suppose a progress then send a message to Handler to so. Inside Handler you can handle message and write a code snippet to Change anything on UI. This is the preferred way for Android. see these link1 , link2 & link3

You use this AsynTask as a inner class of your activity. In do in background do the time consuming task you want to do and then in on postexecute you can show the text message.
call this from your main activity
initTask = new InitTask();
initTask.execute(this);
protected class InitTask extends AsyncTask<Context, Integer, String> {
#Override
protected String doInBackground(Context... params) {
// Do the time comsuming task here
return "COMPLETE!";
}
// -- gets called just before thread begins
#Override
protected void onPreExecute() {
super.onPreExecute();
}
// -- called from the publish progress
// -- notice that the datatype of the second param gets passed to this
// method
#Override
protected void onProgressUpdate(Integer... values) {
}
// -- called if the cancel button is pressed
#Override
protected void onCancelled() {
super.onCancelled();
}
// -- called as soon as doInBackground method completes
// -- notice that the third param gets passed to this method
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Show the toast message here
}
}

Use a handler:
static final int SHOW_TOAST = 0;
public static void showWaitingDialog(final Activity parent, final Runnable runnable, String msg) {
if (StringUtils.isEmpty(msg)) {
msg = "processing...";
}
final ProgressDialog waitingDialog = ProgressDialog.show(parent, "Please Wait...", msg, true);
// execute in a new thread instead of UI thread
ThreadPoolUtil.execute(new Runnable() {
public void run() {
try {
// some time-consume operation
runnable.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
waitingDialog.dismiss();
}
handler.sendMessage(handler.obtainMessage(SHOW_TOAST));
}
});
}
public Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW_TOAST:
//Toast here
break;
}
}
};

The Painless threading article from the android developer resources provides different alternatives depending on the specific SDK version.

Related

Android additional threads and Looper

I am writing a Android application which reads data from a SQLite Database and then displays the data on a next screen. Whenever I was doing a query on the database I would get an error message that too much work is being done on the main thread.
I then put my query in a new Thread:
(new Thread()
{
public void run()
{
Looper.prepare();
try
{
FPJobCardWizard data = dbHelperInstance.loadFPJobCardWizardFull(fitmentHash);
wState.fitmentItemSet(data.fitmentItemGet());
} catch (Exception e) {e.printStackTrace();}
Looper.loop();
}
}).start();
Now the gui/main thread is completing it's operation prior to the Query being complete and as a result the data variable is still empty. I read a few posts and the API documentation and it seems that I need to use a Looper (this seems to be the correct fix) but I have never used a Looper and cannot seem to get it to work.
Please can you check the code above and guide me in the right direction.
Thank you all in advance.
the best choice here will be using an AsyncTask, as it will enables you to perform all the background work in a background thread, then when the result is generated it will apply it using the UI thread:
So, as explained in the life cycle of AsyncTask, you can do all of your background work in the method doInBackground() and then do all of your UI work on the method onPostExecute() which will be executed after taking the result from doInBackground() method according to the life cycle, and to put your hands more on the AsyncTask, have a look at this example which provides the following example code:
public class AsyncTaskTestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// This starts the AsyncTask
// Doesn't need to be in onCreate()
new MyTask().execute("my string paramater");
}
// Here is the AsyncTask class:
//
// AsyncTask<Params, Progress, Result>.
// Params – the type (Object/primitive) you pass to the AsyncTask from .execute()
// Progress – the type that gets passed to onProgressUpdate()
// Result – the type returns from doInBackground()
// Any of them can be String, Integer, Void, etc.
private class MyTask extends AsyncTask<String, Integer, String> {
// Runs in UI before background thread is called
#Override
protected void onPreExecute() {
super.onPreExecute();
// Do something like display a progress bar
}
// This is run in a background thread
#Override
protected String doInBackground(String... params) {
// get the string from params, which is an array
String myString = params[0];
// Do something that takes a long time, for example:
for (int i = 0; i <= 100; i++) {
// Do things
// Call this to update your progress
publishProgress(i);
}
return "this string is passed to onPostExecute";
}
// This is called from background thread but runs in UI
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// Do things like update the progress bar
}
// This runs in UI when background thread finishes
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Do things like hide the progress bar or change a TextView
}
}
}

How to make a periodic code run off the UI thread in Android

The following code is what I'm using currently, but there is an issue that the Toast is being shown, so it probably is in the UI thread isn't it? I do not want the run() function to run on the UI thread as I will probably add some heavy downloading there. However, I want to repeatedly execute this code (after every 9000ms) So what must I do, to either make this run off the UI thread, or a solution to my problem. Thank you.
final Handler handler = new Handler();
Thread feedthread = new Thread()
{
#Override
public void run() {
super.run();
Toast.makeText(context, "UI", Toast.LENGTH_SHORT).show();
handler.postDelayed(this, 9000);
}
};
handler.postDelayed(feedthread, 9000);
Please do not suggest AsyncTask to me unless there is a way to repeat the code without using a while loop wasting resources or setting the thread to sleep. I would like answers to what I asked, and I do not want to run the code on the UI thread.
You need to call the runOnUiThread method to show the Toast
final Handler handler = new Handler();
Thread feedthread = new Thread()
{
#Override
public void run() {
super.run();
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(context, "UI", Toast.LENGTH_SHORT).show();
}
});
handler.postDelayed(this, 9000);
}
};
handler.postDelayed(feedthread, 9000);
You want to use the AsyncTask class. Here is an example to show how it works:
// Async Task Class
private class MyTask extends AsyncTask<String, String, String> {
// (Optional) Runs on the UI thread before the background task starts
#Override
protected void onPreExecute() {
super.onPreExecute();
// Do some UI stuff if needed
}
// Runs on a background thread
#Override
protected String doInBackground(String... param) {
String url = param[0];
// Do something with the param, like kick off a download
// You can also use publishProgress() here if desired at regular intervals
/*while (isDownloading) {
publishProgress("" + progress);
}*/
return null;
}
// (Optional) Runs on the UI thread periodically during the background task via publishProgress()
protected void onProgressUpdate(String... progress) {
// Update UI to show progress
/* prgDialog.setProgress(Integer.parseInt(progress[0])); */
}
// (Optional) Runs on the UI thread after the background task completes
#Override
protected void onPostExecute(String file_url) {
// Do some UI stuff to show completion of the task (if needed)
}
}
You can run your task like this:
String url = getInternetUrl();
new MyTask().execute(url);
Java Thread
new Thread(new Runnable(){
private boolean stopped = false;
#Override
public void run(){
while(!stopped) {
// Do, do, do...
try {
Thread.Sleep(9000);
} catch(Exception e){}
}
}
}).start();
Android Handler
Also you can use Android handler class to run a code periodically. This requires you to have a looper-prepared thread to attach the handler to. Basically, a looper-prepared thread is assign a queue and every message posted to this thread will be queued and processed one by one in a queue manner.
This approach has a difference with the former one and is that if your do a lot of work in that background thread so that takes some time, then subsequent queued messages will be processed quicker than the interval (in this case, 9 seconds). Because looper-enabled threads immediately process the next queued message, once they are done with the previous one.
Find More Info Here
Note: You shouldn't [and can't] use this approach as an alternative to Service. This newly created thread does need an underlying component (either Activity or Service) to keep it alive.

Asynctask is not getting timeout after a thread setup to cancel it after a certain period of time

I am trying to cancel a log run AsyncTask if a certain period of time exceeds (if AsyncTask is not automatically finised)
Below is the code where I setup my task to start with timeout
final ProfileDesc pdsc = new ProfileDesc();
pdsc.execute();
Thread th_pdsc = new Thread(){
public void run()
{
try{
pdsc.get(120000, TimeUnit.MILLISECONDS);
}
catch(Exception e){
pdsc.cancel(true);
((Activity)context).runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(context, "Download Time out. Please Try again later.", Toast.LENGTH_LONG).show();
}
});
}
}
};
th_pdsc.start();
below is the code for my AsynTask
private class ProfileDesc extends AsyncTask<Void, Void, Void> {
protected void onPreExecute() {
dialogue = new ProgressDialog(MainActivity.this);
dialogue.setTitle("Processing");
dialogue.setMessage("Getting Header Information");
dialogue.setIndeterminate(true);
dialogue.setCancelable(false);
dialogue.show();
}
protected void onPostExecute(Void params) {
super.onPostExecute(params);
dialogue.dismiss();
}
protected Void doInBackground(Void... arg0) {
//long run work
return null;
}
}
After two minutes it's still running. How can I set up the time out? Note: I have followed this link of Stack Overflow for this code.
What you had
ProfileDesc pdsc = new ProfileDesc();
pdsc.execute();
was enough. There is no need for a Thread. doInBackground is invoked on the background thread. So you can do you Network operations in doInbackgorund.
Secondly calling get makes AsyncTask no more Asynchronous as it blocks the ui thread
get(long timeout, TimeUnit unit) Waits if necessary for at most the
given time for the computation to complete, and then retrieves its
result
I guess you have misunderstood the use of Asynctask. Read the docs
http://developer.android.com/reference/android/os/AsyncTask.html
You may want to check this
Stop AsyncTask doInBackground method
Here new thread is not needed.Just remove "dialogue.setIndeterminate(true)". It means the "loading amount" is not measured.I think it's creating the problem.

Android progress dialog force showing

I have this lines of code:
1) m_ProgressDialog = ProgressDialog.show(m_Context, "", m_Context.getString(R.string.dictionary_loading));
2) //important code stuff: interact with db, change some textview values (= 2-3 seconds if i'm unlucky)
3) m_ProgressDialog.dismiss();
But what happens is that phase 2) happens before 1).. which is wrong. First UI freezes then dialog appears..
phase 2) is some code that interacts with DB, might also change some textViews..but since this might take a while i decided to show that progress dialog so that user would know that really important stuff is going on. I cant use Async for these operations since UI code & db code is mengled, it will only complicate my life
How can i force dialog to show at request ??.. to me it seams that code presented just adds it in a "To do list when i have some free time & i dont have time now" stack..
You are doing your work on the ui thread. You should use a separate thread for this to keep the UI (progress bar) responsive. Have a look at AsynchTask.
Do not use UiThread for background operations it lead to freeze of screen.You have to use separate thread like Asyc Task.
do like below
in
onCreate()
{
dialog.show();
new DownloadFilesTask().excute()
}
class DownloadFilesTask extends AsyncTask<Void,Void,Void>
{
protected Long doInBackground(URL... urls) {
//Background operation
}
return null;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(Long result) {
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
//Update you Ui here
dialog.dismiss();
}
});
}
}
For most of cases if you want to simply have 2 methods, ShowLoading() and HideLoading() just use this
public static void ShowLoading()
{
HideLoading();
myLoadingThread = new Thread(new ThreadStart(LoadingThread));
myLoadingThread.Start();
}
private static void LoadingThread()
{
Looper.Prepare();
myProgressDialog = new ProgressDialog(myActivity,
Resource.Style.AppTheme_Dialog);
myProgressDialog.SetMessage("Loading..."); // Or a #string...
myProgressDialog.SetIcon(Resource.Drawable.your_loading_icon);
myProgressDialog.SetProgressStyle(ProgressDialogStyle.Spinner);
myProgressDialog.SetCancelable(false);
myProgressDialog.Show();
Looper.Loop();
}
public static void HideLoading()
{
if (myProgressDialog != null)
{
myProgressDialog.Dismiss();
myProgressDialog = null;
}
if (myLoadingThread != null)
myLoadingThread.Abort();
}
Now I declare and explain the followings variables I used on my code sample, one of them is global, yes, if you don't like to use global vars, or you want to have 2 loading dialogs at a time (wtf...) look for another solution. This is just the simplest way, most friendly and free of weird code with nested methods, new classes and inheritance everywhere for such a simple thing:
private Thread myLoadingThread;
private ProgressDialog myProgressDialog;
// Some people will hate me for this, but just remember
// to call myActivity = this; on each OnStart() of your app
// and end with all your headaches
public Activity myActivity;

How to work with AsyncTask and threads?

The goal:
Using Google App Engine server and Android client, I'm trying to put on the Google map at the Android client Users overlays. Every 30 seconds I'm polling the server and getting Vector that contains users and adding it to the map.
Current status:
I'm dong all that using in one new thread, So after running the app I got:
weird behaviors(delayed overlays, multiple overlays) and after that crushed with ConcurrentModificationException.
After reading a bit i figured out that I need to work with AsyncTask.
Correct me if I'm wrong,But I understand that everything done in the Activity at at onCreate is "running" in UIhread so I need to put the "Logic" (All the Network handling) in doInBackground and all the UI Handling like putting overlays on the map in onPostExecute.
My Question are:
1) In the current status I'm doing:
new Thread()
{
#Override
public void run()
{
super.run();
while(true)
{
SystemClock.sleep(30000);
Vector responseFromServer = getUsersVectorFromServer();
putNewOnlineUserOnTheMap();
}
}
}.start();
What is the right way to convert this To AsyncTask?
Do I poll the server still using new thread in the doInBackground or there is right way to do this?
2) Is there a specific list of what counts as UI to put in onPostExecute or any concepts list?
In my case I guess that in need to put putNewOnlineUserOnTheMap() in onPostExecute.
Thanks.
Something similar to the following:
class UpdateTask extends AsyncTask<Void, Vector, Void>{
#Override
protected Void doInBackground(Void... params) {
// this is running in a background thread.
while (!isCancelled()) {
SystemClock.sleep(30000);
Vector responseFromServer = getUsersVectorFromServer();
// send the result back to the UI thread
// onProgressUpdate will be called then
publishProgress(responseFromServer);
}
return null;
}
#Override
protected void onProgressUpdate(Vector... values) {
// this is executed on the UI thread where we can safely touch UI stuff
putNewOnlineUserOnTheMap(values[0]);
}
}
You can't use the result of the task since the task is finished then. But you can use the progress publishing mechanism to get periodic results. If you use it like that and do the modification on the UI thread you should not get ConcurrentModificationException because you do the modifications on the one thread that can safely modify the UI.
One thing to note here: create new instances of your Vector in the background thread and then use it to update the UI. But don't touch the same object afterwards in the backgroundthread. That way you don't need any synchronization since after the background thread sends it away it is only the UI thread that touches it. (and you could use a simple ArrayList instead of a Vector)
AsyncTask uses generics and varargs.The parameters that are passed to the asyntask are . TypeOfVariableArgumentsParameters is passed into the doInBackground(), ProgressParam is used for progress information and ResultParam must be returned from doInBackground() and is passed to onPostExecute() as parameter.
example:--
protected class ParsingTask extends AsyncTask> {
private ProgressDialog loadingDialog = new ProgressDialog(JsonParserActivity.this);
protected void onPreExecute() {
loadingDialog.setMessage("loading app store..");
loadingDialog.show();
}
#Override
protected ArrayList<Items> doInBackground( Context... params ) {
// do ur process here.
return result;
}
if (!this.isCancelled()) {
}
return result;
}
#Override
protected void onProgressUpdate(String... s) {
super.onProgressUpdate(s);
Toast.makeText(getApplicationContext(), s[0], Toast.LENGTH_SHORT).show();
}
#Override
protected void onPostExecute( ArrayList<Items> response ) {
//if u r dealing with list view and adapters set the adapter here at the onPostExecute()
loadingDialog.dismiss();
}
#Override
protected void onCancelled() {
super.onCancelled();
Toast.makeText(getApplicationContext(), "The operation was cancelled", 1).show();
}
}
You can use AsyncTask like below. Hope this will help you..
Class YourClass{
void YourClass(){
NetworkTask nT = new NetworkTasK();
nT.execute();
}
}
protected class NetworkTask extends AsyncTask<Void, String, Boolean>
{
#Override
protected Boolean doInBackground(Void... params)
{
try
{
String response;
while(keepreceiving)
{
response = in.readLine();//Prog Counter stops here until getting i/p.
if(response != null)
yourFunctionForResponse(response);
}
}
catch (Exception ex)
{
}
return null;
}
private void yourFunctionForResponse(String response){
//things to do....
}
}
You may also try runOnUiThread(Runnable action) along with this to implement your work.

Categories

Resources