I am using this code to display a Progress Dialog which is working fine:
dialog = ProgressDialog.show(this, "Please wait",
"Gathering Information...", true);
Thread thread = new Thread()
{
#Override
public void run() {
if(Chapter_sync.size()>0){
storemodule();
c.open();
for(int i=0;i<Chapter_sync.size();i++)
{
downloadPDF(Chapter_sync.get(i));
System.out.println("SYNCED"+i);
c.update(Chapter_sync.get(i));
}
}dialog.dismiss();
}
};thread.start();
LinearLayout parentlayout=(LinearLayout)findViewById(R.id.chapterholder);
parentlayout.removeAllViews();
setUpViews();
}
}
Here what I am trying to do is display a Progress dialog till all computation is done.
As it completes i wanted to setup all views again. But the setUpViews() is called before the thread starts. I am not so good at thread basics .Could any one help me understand why is this happening and how can I get my own results?
The problem is you are not using handlers. Simply do this,
dialog = ProgressDialog.show(this, "Please wait",
"Gathering Information...", true);
Thread thread = new Thread()
{
#Override
public void run() {
if(Chapter_sync.size()>0){
storemodule();
c.open();
for(int i=0;i<Chapter_sync.size();i++)
{
downloadPDF(Chapter_sync.get(i));
System.out.println("SYNCED"+i);
c.update(Chapter_sync.get(i));
}
}dialog.dismiss();
}
handler.sendemptyMessage(0);
};thread.start();
And in your onCreate() create Handlers,
Handler handler=null;
handler=new Handler()
{
public void handleMessage(Message msg)
{
progressDialog.cancel();
if(msg.what==0)
{
LinearLayout parentlayout=(LinearLayout)findViewById(R.id.chapterholder);
parentlayout.removeAllViews();
setUpViews();
};
You can't update your UI from background thread. Either you have to use AsyncTask or to use handlers from your background thread to inform your main thread that the background action has been completed.
Thread scheduling is dependent on the operating system. So instantiating your thread does not ensure that your thread will run whenever you want.
The problem you are facing can be best handled using async task. Or if you have a callback that lets you know when your download is completed then you can dismiss the dialog on the callback. Make sure you dismiss it inside a UI thread by doing.
mActivity.runOnUiThread() or any other such methods.
In your code if u see
After Starting the Thread you have call your method setUpViews(), which does not wait for your thread to complete and setups your views.
Use Handler.post after the dialog is dismissed in your thread which gather your information.
handler.post(new Runnable()
{
setUpViews();
});
So after the your operations completed your setupViews will be called by your Handler.
Related
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.
I have a Button, and upon pressing it, the onClick() would process user's request. However, this takes a little time, so I would like to have a View showing "Please wait, processing..." immediately upon pressing this Button, while its OnClickListener does its thing.
My problem is, this "Please wait, processing..." which I placed at the very beginning of onClick(), only appears AFTER the whole onClick() is done. In other words, after the whole processing is done. So, I was wondering, how do I make a View saying "Please wait, processing..." before the actual processing has begun?
As #Blundell pointed you may process long-running operation on a separate thread to avoid freezing of UI thread. However in Android there's a better alternative for general-purpose Handler which is called AsyncTask. Please refer to this tutorial for details.
You can do this by just using AsyncTask without dealing anything else.
First create new AsyncTask class on "onPreExecute" change ui to show
that you are processing sth
Second do your all backend time consuming job on "doInBackground"
method (do not call any ui updating method from here)
Third change your ui to show that process is finished or whatever you
wanna do.
yourUiButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
new NewTask().execute();
}
});
class NewTask extends AsyncTask<String, Void, Task>{
#Override
protected void onPreExecute() {
super.onPreExecute();
//this part runs on ui thread
//show your "wait while processing" view
}
#Override
protected Task doInBackground(String... arg0) {
//do your processing job here
//this part is not running on ui thread
return task;
}
#Override
protected void onPostExecute(Task result) {
super.onPostExecute(result);
//this part runs on ui thread
//run after your long process finished
//do whatever you want here like updating ui components
}}
Do the processing on another thread so that the UI can show your dialog.
// Show dialog
// Start a new thread , either like this or with an ASyncTask
new Thread(){
public void run(){
// Do your thang
// inform the UI thread you've finished
handler.sendEmptyMessage();
}
}
When the processing is done you will need to callback to the UI thread to dismiss oyur dialog.
Handler handler = new Handler(){
public void handleMessage(int what){
// dismiss your dialog
}
};
AsyncTasks.
Place the displaying of the progress dialog in onPreExecute
Do your thing in doInBackground
Update whatever needs to be updated in the UI, and close the dialog in onPostExecute
You will need something like this
public void onClick(View v){
//show message "Please wait, processing..."
Thread temp = new Thread(){
#Override
public void run(){
//Do everything you need
}
};
temp.start();
}
or if you want it to run in the UIThread (since it is an intensive task, I don't recommend this)
public void onClick(View v){
//show message "Please wait, processing..."
Runnable action = new Runnable(){
#Override
public void run(){
//Do everything you need
}
};
v.post(action);
}
put ur code inside a thread and use a progress dialogue there...
void fn_longprocess() {
m_ProgressDialog = ProgressDialog.show(this, " Please wait", "..", true);
fn_thread = new Runnable() {
#Override
public void run() {
try {
// do your long process here
runOnUiThread(UI_Thread);//call your ui thread here
}catch (Exception e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(null, thread1
"thread1");
thread.start();
}
then close your dialogue in the UI thread...hope it helps..
I'm using a thread so that I can show a progress dialog while my app loads some data. If there is an error it will stop the progress dialog and show the popup saying "error". However I found out that alert dialogs cannot run inside a UI thread and that I need to use a Handler. Can someone with help with this issue? Here is my code. Thanks
verifyCode.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
final ProgressDialog progressDialog = ProgressDialog.show(
Activate.this, "", "Loading...");
new Thread(new Runnable() {
public void run() {
try {
new AlertDialog.Builder(Activate.this)
.setTitle(getResources().getString(R.string.InvalidKey))
.setMessage(getResources().getString(
R.string.PleaseEntervalidRegistration)).setNeutralButton(
"OK", null).show();
progressDialog.dismiss();
//more code
}).start();
}
You can't make changes to UI element on non-UI threads. onClick will run on the UI thread, but since you spawn a Thread inside onClick then non-UI elements cannot be manipulated from inside that Thread. Move your AlertDialog and ProgressDialog calls to just prior to spawning the new Thread.
Also, as #lightblade suggested, If you need to do some sort of action which requires heavy background processing and UI manipulation based on that processing, then you should use AsyncTasks. It provides methods you can override for pre-processing, actual processing, post-processing, and updating progress.
I need to display a message to the user "Communicating to the Server...Please wait for few seconds" when a call to a webservice is made. Currently I'm using Toast.makeText to display the message. For some reason, I don't see the message pop-up. But interestingly when I comment the web service method call, I see the Toast message.
Toast.makeText(this, "Communicating to the Server...Please wait for few seconds",
Toast.LENGTH_SHORT).show();
//webservice code goes here...
Or any other alternative to satisfy this requirement is also fine.
Have you looked at using AysncTask. Using AsyncTask you can show a dialog with your message on onPreExecute().
Do NOT mix UI code and network code. See: http://developer.android.com/resources/articles/painless-threading.html
You can use AsyncTask to run your service and show Toast in onPreExecute.
Or you can use normal Thread but, you'll need to use Handler. Here is how:
class MyActivity extends Activity
{
final Handler mHandler;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(...);
mHandler = new Handler();
...
}
void showToast(final String text)
{
mHandler.post(new Runnable()
{
#Override
public void run()
{
Toast.makeText(MyActivity.this, text, Toast.LENGTH_LONG).show();
}
});
}
class MyThread implements Runnable
{
#Override
public void run()
{
showToast("your custom text");
//your service code
}
}
}
And here is how you start the thread:
Thread thread = new Thread(new MyThread());
thread.run();
The problem is that the UI thread is blocked as soon as you make the blocking web service call, so it never updates with the toast message. By the time it returns, the time for toast message has expired.
Run your web service call in a thread, using AsyncTask, or just create a thread like,
new Thread(new Runnable() {
public void run() {
// WS call here
}
}).start();
Take care that if you create your own thread, you can only update the UI from the UI thread, so you'll need to use Handler.post() or sendMessage() to run the UI update on the UI thread.
http://developer.android.com/reference/android/os/AsyncTask.html
http://developer.android.com/reference/android/os/Handler.html
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);