Progress Dialog and Threading - android

I am targeting Android 4.0 and am communicating with a telemetry device using TCP/IP. Android 4.0 forces all networking to be done in a separate thread. First I open a socket, then I contact the device and download some information all from a separate thread. At this point I want to display a progress dialong to show the progress of downloading more detailed information. My problem is that I cannot show the progress dialog from anywhere but the main UI. But, I do not know when I have reached the point in the other thread where I am ready to display the progress dialog. Is there some way I can check for this from the main UI without tying up the system?

Use Handler, like that :
final int PROGRESS_BY = 1;
final Handler handler = new Handler()
{
public void handleMessage(android.os.Message msg)
{
switch (msg.what)
{
case PROGRESS_BY :
progressBar.setProgress((Integer) msg.obj);
break;
}
}
};
Thread thread = new Thread()
{
#Override
public void run()
{
super.run();
// do something
Message msg = new Message();
msg.what = PROGRESS_BY;
msg.obj = new Integer(10);
handler.sendMessage(msg);
// do something
[...]
}
};

AsyncTask is framework provided utility that is meant for cases like you describe.
From the other thread, i.e the one in which the async task is executing, you can publish progress using publishProgress() method of AsyncTask. Its asynchronous and runs on a different thread but has event callbacks that run on main thread. OnProgressUpdate() is the method where you can work with a progress dialog.
http://developer.android.com/reference/android/os/AsyncTask.html

To trigger the dialog on your main ui, you need to use 'context.runOnUiThread()' where context is the reference to your display activity. It's also worth looking into using an AsyncTask.
Here is an android blog post that explains everything in detail: http://android-developers.blogspot.ca/2009/05/painless-threading.html
As an aside, you can also just start displaying a indeterminate progress dialog from the start, so the user is never waiting without visual feedback, then switch to the determinate when you know the download details.

Related

Show progress Dialog while the UI gets customized

I already have idea on how to use a Progress Dialog when background action is being performed. But my question is how do I show a progress Dialog when I am dynamically inflating a huge layout.
Since I can't inflate a view in another Thread, I am using the main UI thread. Due to this my progress dialog is not getting priority and it doesn't show up. My UI hangs for several seconds until it gets loaded fully. I tried several approcahes but none seems to work.
progress.show(context,"","inflating UI...");
setNewContent(R.layout.my_profile,R.id.my_profile_menu_button,R.id.my_profile_all_elements_layout);
populateProfileList(); //Dynamic nested layouts being inflated.
I am basically looking for dynamic layout changes based on user actions. So I dont have any other way other than creating dynamic views. Can anyone suggest me a helpful idea.
I had an similar problem with ui-thread. I wanted to add much views to my layout at runtime, I wanted to show a ProgressDialog to inform the user, that it could take a while. I had tried it with AsyncTask, but the only chance to do this, was to implement my ui-methods into the onPostExecute-Method of AsyncTask. But this just freezes the ProgressDialog, because ProgressDialog even works on ui-thread. I found a solution, maybe not the best, but it works. Before starting ui-action, I show a Toast. Then, I created a Thread with a handler and delayed the execution. After ui-action was done, I showed a new Toast. Delay the thread, gives the Toast enough time to get showed:
Toast.makeText(ActivityContext.this,
R.string.start_message,
Toast.LENGTH_SHORT).show();
final Handler uiHandler = new Handler();
final Thread uiThread = new Thread(new Runnable() {
#Override
public void run() {
uiHandler.postDelayed(new Runnable() {
#Override
public void run() {
yourUIAction();
Toast.makeText(
ActivityContext.this,
R.string.finish_message,
Toast.LENGTH_SHORT).show();
}
}, 100);
}
});
uiThread.start();
You need to use a handler to be able to talk to the UI thread
//in some thread
uiHandler.sendEmptyMessage(1);
...
Handler uiHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if(msg.what == 1) {
//do somestuff
}
}
};
Using Async Task is much better idea to me, when you have to do something in background, while progress dialog shows up on screen and then when background task completes, update UI... for reference please follow the link...
http://labs.makemachine.net/2010/05/android-asynctask-example/
hope this helps...:-)

Starting an android activity from a worker thread?Is this a good practice

What i am trying to do over here is that I want to call a webservice and based on its response i might invoke another webservice or start an activity.I am already writing the web service in a separate thread but the issue is that i am calling the activity in a worker thread,
To make myself more clear i have put my pseudo code.
if (User ID and Password present in the shared preference) THEN
Utils.checkauthorisation(API) //Web Service Call
if(respsonse is Paswordexpired)
erase password from DB
Goto (LOGIN SCREEN)//startActivity Call
else if(download of images hasnt happened today)) THEN
UTILS.DownloadImages//Web service call
if(response==connectivityorOtherError)
Toast respective Message
GOTO (GALLERY SCREEN)//startActivity Call
else if (response==confilicted Data)
Goto (CHANGES SCREEN)//startActivity Call
endif
endif
endif
I was planning to show a progress bar and do all these events in a thread like this
progressDialog = ProgressDialog.show(this, "Loading",
"Authenticating Please wait.");
new Thread() {
public void run() {
///execute the pseudo code
startActivity(intent); //Is this a good practice
Message msg = Message.obtain();
msg.what = 1;
messagHandler.sendMessage(msg);
}
}.start();
private static Handler messagHandler = new Handler() {
public void handleMessage(Message message) {
super.handleMessage(message);
switch (message.what) {
case 1:
progressDialog.dismiss();
break;
default:
break;
}
}
};
But something that disturbs me is that I have to start an activity in a worker thread here. Is this good practice? I initially thought that we could only start an activity from the UI thread. What is the process happening in the back end here(in the thread sense)? If this is not a good practice what are the other alternatives to implement my pseudocode?
P.S.:Sorry about asking this question again.I had asked the same question earlier but had failed to convey what i wanted exactly so had received answers for alternatives to starting activity on worker thread(part of my question) but didn't recieve any answer on "is this a good practice"
Thanks
I can't fully understand where you're starting the activity, but assuming it's in the "GOTO" lines of your pseudo-code, I would advise you to set the msg.what with different values for each activity you want to launch and then launch it on the handleMessage(Message).
This is assumes that the Handler is created in the UI thread. If it's not, you shouldn't dismiss the ProgressDialog as well since both things should be done from the UI thread. Create one on the UI thread and get it there.

Specifics on using Looper.prepare() in Android

I'm having a bit of trouble understanding how to use the Looper prepare()/loop()/quit() logic.
I have three threads: one is the UI thread, one is a game logic thread and the last is a network communication thread (a background thread, lives only while being used).
The game thread has many dependencies on the results of the network calls, so I wanted to spin the network thread off of the game thread and have a Handler post the result back.
Of course, since the UI thread is not involved I need to call Looper.prepare()... somewhere. I thought it should be called in the game thread, but I can't do that because loop() takes it over.
How do I go about posting back to the game thread from network thread with my handler?
What's going on is that once you call Looper.prepare() followed by Looper.loop() on a Thread, all that Thread will ever do is service its MessageQueue until someone calls quit() on its Looper.
The other thing to realize is that, by default, when a Handler is instantiated, it's code will always execute on the Thread it was created on
What you should do is create a new Thread and in run() call Looper.prepare(), setup any Handlers, and then call Looper.loop().
Bearing these things in mind here is the basic pattern I use a lot of places. Also, there's a good chance you should just be using AsyncTask instead.
public class NetworkThread extends Thread {
private Handler mHandler;
private Handler mCallback;
private int QUIT = 0;
private int DOWNLOAD_FILE = 1;
public NetworkThread(Handler onDownloaded) {
mCallback = onDownloaded;
}
public void run() {
Looper.prepare();
mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
// things that this thread should do
case QUIT:
Looper.myLooper().quit();
break;
case DOWNLOAD_FILE:
// download the file
mCallback.sendMessage(/*result is ready*/);
}
}
}
Looper.loop();
}
public void stopWorking() {
// construct message to send to mHandler that causes it to call
// Looper.myLooper().quit
}
public void downloadFile(String url) {
// construct a message to send to mHandler that will cause it to
// download the file
}
}
Could you tell some examples for what you are using your network thread? I think you can solve your problems without using Looper.
You can use ASyncTask to perform background task that may update some values in your UI thread. If user has to wait until background operation will be finished, you can show ProgressDialog and block application in OnPreExecute method, and then hide it in onPostExecute.
As I said, please describe more your needs and target which you want to achieve.

Cannot get ProgressDialog to display in Thread

Well I've seen a wide variety of failures while trying to get this to work. I have a thread that is started via an Activity. The thread needs to create/display progress dialogs and dismiss them.
When I tried to directly display the ProgressDialog I got an error that my Looper wasn't prepared. I looked up with a Looper was an implemented it. However, I had to call Looper.loop for the progress dialog to show up. After it showed up the application froze on that point never to continue past the Looper.loop call.
I couldn't get it to work so looked for a whole new way using a HandlerThread and a Handler. I create a HandlerThread and start it. I get the looper from the thread and create a Handler with it. My ProgressDialog or Toasts won't show up at all.
Is there an easier way to go about doing this?
U can have an
private Handler stopProgressHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
setProgressBarIndeterminateVisibility(false);
}
};
private Handler startProgressHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
setProgressBarIndeterminateVisibility(true);
}
};
so that when u start the thread start the progressbar and after thread is completed u can stop the progressbar.
public void closeProgressbar(){
//bluetoothconnector.onDestroy();
stopProgressHandler.sendEmptyMessage(0);
}
public void openProgressbar(){
//bluetoothconnector.onDestroy();
startProgressHandler.sendEmptyMessage(0);
}
This will help to call the progressbar to start and stop.. This will be one of the solution..
Not sure about ProgressDialog, but all UI related stuff in Android, as far as I know, required to be updated in UI Thread. There's actually an easy helper class for implementing async task: http://developer.android.com/reference/android/os/AsyncTask.html
Alternatively, you can create a Handler (which would be on UI Thread) and create the dialog using that:
Handler uiHandler;
//Activity onCreate
onCreate(...){
uiHandler = new Handler();
}
// Somewhere in your other thread,
uiHandler.postRunnable(new Runnable(){
#Override
public void run(){
// Create or update dialog
...
}
});
The last answer is wrong....
it should be:
setProgressBarIndeterminateVisibility(Boolean.TRUE | Boolean.FALSE);

Task not finishing and forbidding TextView to be updated

I am now working on an android app in which I need to display a text after some processing is done.
I'm using a Thread to run a process in the back while my progress dialog is being displayed to the user. The Thread works properly and I've followed it step by step and, apparently, it also ends fine; however, the method in which I call it does not seem to come to an end (at least, during a normal cycle) because the text I am setting afterward does display immediately, I have to wait and do some other action (like in order for it to display
Below is the piece of code I'm having trouble with:
private OnClickListener saldoDisp = new OnClickListener(){
public void onClick(View v){
int x = s2.getSelectedItemPosition();
branchSel = arrSucsId[x];
mainProc();
saldoAdminTex.setText(strSaldo); //The late one
}
};
public void mainProc(){
chekP = new Thread (null,doProc,"Background");
chekP.start();
mProgress =ProgressDialog.show(SivetaAsaldo.this, "","Obteniendo saldo...",true, false);
}
private Runnable doProc = new Runnable(){
public void run(){
if(getSaldoAdmin(levelSel,branchSel))
{
mProgress.dismis();
Log.i(TAG,"Task completed properly");
}else
handler.post(tosti);
}
};
So I do get the "Task completed properly" but seems like it still waits for something else, any clues guys?
Thanks for taking a bit of your time to check it out =).
saldoAdminTex.setText(strSaldo); //The late one
is going to get called immediately. It doesn't wait until after the Thread started in mainProc ends. You also cannot dismiss the Progress Dialog in your runnable. You can only do UI related things on the main UI thread.
It would help you to read the article on Painless Threading on the Android Dev site.
About your ProgressDialog, please see this answer about how to use a AsyncTask with a ProgressDialog.
Looking at your code, this:
saldoAdminTex.setText(strSaldo);
would potentially be executed before your thread finishes as the thread will be running in parallel to that line.
An alternative way would be to do this:
public void mainProc(){
mProgress =ProgressDialog.show(SivetaAsaldo.this, "","Obteniendo saldo...",true,false);
handler.post(new Runable(){
public void run(){
if(getSaldoAdmin(levelSel,branchSel))
{
mProgress.dismis();
saldoAdminTex.setText(strSaldo);
Log.i(TAG,"Task completed properly");
}else
handler.post(tosti);
}
});
}

Categories

Resources