I need to process some data when the user click the button in one activity, so the screen looks like the app stops for 2-3 seconds. It isn't a lot but I want to give the user information that everything is ok and IMO the best way will be the progressbar which is visible only when data are processed.
I found the code of ProgressBar and it looks like this:
<ProgressBar
android:id="#+id/loadingdata_progress"
style="?android:attr/progressBarStyle"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignBottom="#+id/fin2_note"
android:layout_centerHorizontal="true"
android:indeterminate="true"
android:visibility="invisible" />
and inserted it on the middle of my layout.
And to try if the progressbar works, I put this code
loadingimage= (ProgressBar) findViewById(R.id.loadingdata_progress);
loadingimage.setVisibility(View.VISIBLE);
into onCreate method and everything looks fine.
Then I recreated the code to show this progressbar only if the data is processed.
After click the user invoke this method
public void fin2_clickOnFinalization(View v)
{
loadingimage= (ProgressBar) findViewById(R.id.loadingdata_progress);
loadingimage.setVisibility(View.VISIBLE);
// code where data is processing
loadingimage.setVisibility(View.INVISIBLE);
}
and nothing appear on the screen. I don't know where is the mistake. If I found the progress bar by id, It's strange for me that I can control it in onCreate method but in onclick method it's out of my control.
Your UI thread cannot show progress bar cause it is busy due to your data processing. Try to use this kind of code :
public void fin2_clickOnFinalization(View v) {
new YourAsyncTask().execute();
}
private class YourAsyncTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... args) {
// code where data is processing
return null;
}
#Override
protected void onPostExecute(Void result) {
loadingimage.setVisibility(View.INVISIBLE);
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
loadingimage.setVisibility(View.VISIBLE);
}
}
EDIT:
AsyncTask let you run code in separate thread and make app more responsive, just put time-consuming code inside doInBackground.
You're not giving the UI time to refresh. Your "data processing" code is running on the UI thread, blocking any visible changes. By the time the system gets control to refresh the display, you've already set it back to invisible.
To fix this, move your processing code to a separate thread or AsyncTask. Then you can set the progress bar to visible, start the task, and have it turn itself invisible once it's done.
I'd recommend AsyncTask for this purpose about 90% of the time on Android, since it comes stock with useful callbacks. The developer guide for it(in the Javadoc linked above) is pretty explicit, and outlines all the steps you need to take.
AsyncTask is too heavily-weighted for such task.
A better much solution
Handler handler = new Handler(getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
loadingimage.setVisibility(View.VISIBLE);
}
});
Or even simpler (does essentially the same thing as solution above)
runOnUiThread(new Runnable() {
#Override
public void run() {
loadingimage.setVisibility(View.VISIBLE);
}
});
You can try to create a global ProgressDialog not in the layout but in your activity like:
public class MyActivity {
ProgressDialog progress = null;
protected void onCreate(...) {
progressDialog = new ProgressDialog(this);
progressDialog.setCancelable(false);
progressDialog.setTitle("Progress");
}
public void fin2_clickOnFinalization(View v)
{
progress.show();
// code where data is processing
progress.dismiss();
}
}
Hope i it helps
Related
Here is my code for Progress Dialog in Android and i am getting following error:android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. I saw all previous post related to this error but i could not correct this error.
// Waiting screen
pleaseWaitdialog = ProgressDialog.show(PhoneBookListView.this, "Loading", "Please wait...", true);
new Thread(new Runnable() {
#Override
public void run()
{
Looper.prepare();
// do the thing that takes a long time
LoadContactFromPhoneAndSim();
PhoneBookListView.this.runOnUiThread(new Runnable() {
#Override
public void run()
{
pleaseWaitdialog.dismiss();
}
});
}
}).start();
Any help will be appreciate
Thanks.
I suggest you use an AsyncTask, as they make this sort of thing easier. In general, you want to do complex stuff on a background thread, and only update the UI from the UI thread.
public class PhonebookLoader extends AsyncTask<Void,Void,Void> {
protected Void doInBackground(Void ... params) {
LoadContactFromPhoneAndSim();
return void;
}
protected void onPostExecute(Void param) {
pleaseWaitdialog.dismiss();
}
}
To start it with this class, you just call this:
new PhonebookLoader.execute();
And you can do all kinds of things with this, like publish your progress so the user knows how far they have progressed, update the UI thread after you are done loading, etc. AsyncTask is your friend, use it.
Looking at this, I suspect that PhonebookLoader is probably both loading the data and putting it on the UI. Separating these two tasks will make your app much more responsive and easier to maintain.
In one activity of my app I make a bunch of edit text fields dynamically and then set them with some text from sharedpreferences. I realise that this is a bit much for the main thread to handle which is why there is some lagging of the app when it loads. I am quite new to the concept of threads so I was wondering what the best way was to put the loading of the strings from sharedpreferences into another thread and then just display a loading bar(or similar) in the meantime(in the main thread I guess). Please explain in great detail because threads are new to me.
Also if there are any tutorials on this that point me the the right direction they would also be useful. Thanks in advance.
AsyncTask is what you need.
Create a class that extends AsyncTask
Do your heavy work in doInBackground()
Example:
Class Example extends AsyncTask{
#Override
protected void doInBackground(Object... args){
//do ur stuff
}
#Override
protected void onPostExecute(Object arg){
//do what you wanna do after doInBackground
}
}
Call your task by new Example().execute();
Whilst only the main thread can make changes to the UI, you can you the AsyncTask class to do all the other work on another thread and then push things to the main thread as they are ready to be put on the UI.
YOu can have something like this: Just to guide you
final ProgressDialog pd = ProgressDialog.show(context, "Title", "Loading");
new Thread(new Runnable()
{
#Override
public void run()
{
//get data from shared preferences
runOnUiThread(new Runnable()
{
#Override
public void run()
{
pd.dismiss();
//set that text to your dynamic textview
}
});
}
}).start();
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;
I'm using a standard ProgressDialog implementation: I set up a thread to run a long task, and when it's done it dismisses the ProgressDialog.
#Override
public void onCreate( Bundle bundle ) {
super.onCreate( bundle );
context = this;
progress = ProgressDialog.show( this, "Running", "Please wait..", true, false);
progress.setOnDismissListener( new OnDismissListener() {
public void onDismiss(DialogInterface dialog) {
showResults();
}
});
new DeleteThread().start();
}
And the Thread looks like this:
private class DeleteThread extends Thread {
public DeleteThread() {}
#Override
public void run() {
// long process during which we populate
// a LinearLayout with many other Views
progress.dismiss();
}
}
And in showResults() we take the LinearLayout now filled with Views and set it as the content of an AlertDialog.
The problem is, the ProgressDialog goes away and there's still a long period of time (10-12sec) where nothing is happening before the AlertDialog pops up. Is there a way to make this transition instantaneously?
I know this answer might be coming in a bit late, but what the heck.
I see that you're triggering the showResults() method from the onDismiss callback. I would suggest you do it the other way around. To do that you may need to use the AsyncTask class.
The AsyncTask allows you to easily setup tasks to run in a spawned thread, to update a progress bar if needed (not required, but might be a nice touch in your case) and of course to run some code on the UI thread once the spawned thread completes. For your case, I would place your populating of layoutview in the AsyncTask.doInBackground() method. Then, you'd want to add the showResults() method call in AsyncTask.onPostExecute(). At the bottom of onPostExecute() you should then dismiss your progress dialog. That SHOULD give you the results you want.
As a bonus, you might want to create a constructor for your AsyncTask class and place the creation of the ProgressDialog in there. That way the ProgressDialog will be completely encapsulated within that class and everything is nice and clean. So, something like this:
class MyAsyncClass extends AsyncClass
{
ProgressDialog m_progress;
public MyAsyncClass()
{
m_progress = ProgressDialog.show( this, "Running", "Please wait..", true, false);
}
protected Long doInBackground(Object... data) {
// Do your long process of populating a LinearLayout with many other Views
}
protected void onPostExecute(Long result) {
showResults();
m_progress.dismiss();
}
}
NOTE: Above needs some extra parameters to the class, but you get the idea.
I'm going to venture a guess as a novice Android developer and suggest that while the pointers are generated for the LinearLayout, the layout itself hasn't been populated with content and therefor is populating when you call progress.dismiss()
You will probably have to render the view prior to setting to the AlertDialogs content. http://developer.android.com/guide/topics/ui/how-android-draws.html might have some help in that respect, unfortunately my laptop is have HDD issues so I don't have the Android Development Environment installed and can't try it. But I'd try an invalidate on the LinearLayout right before progress.dismiss(), I hope that helps :S
Make use of something like this below and use an AsyncTask that dismisses the dialog once it is done:
final ProgressDialog progressDialog = new ProgressDialog(v.getContext());
progressDialog.setCancelable(false);
progressDialog.setMessage(v.getContext().getText(R.string.defaultQuantities));
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMax(100);
new CountDownTimer(250, 250) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
if (progressDialog.getProgress() < 100) {
progressDialog.show();
}
}
}.start();
I'm trying to create a ProgressDialog for an Android-App (just a simple one showing the user that stuff is happening, no buttons or anything) but I can't get it right. I've been through forums and tutorials as well as the Sample-Code that comes with the SDK, but to no avail.
This is what I got:
btnSubmit.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
(...)
ProgressDialog pd = new ProgressDialog(MyApp.this);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage("Working...");
pd.setIndeterminate(true);
pd.setCancelable(false);
// now fetch the results
(...long time calculations here...)
// remove progress dialog
pd.dismiss();
I've also tried adding pd.show(); and messed around with the parameter in new ProgressDialog resulting in nothing at all (except errors that the chosen parameter won't work), meaning: the ProgressDialog won't ever show up. The app just keeps running as if I never added the dialog.
I don't know if I'm creating the dialog at the right place, I moved it around a bit but that, too, didnt't help. Maybe I'm in the wrong context? The above code is inside private ViewGroup _createInputForm() in MyApp.
Any hint is appreciated,
you have to call pd.show before the long calculation starts and then the calculation has to run in a separate thread. A soon as this thread is finished, you have to call pd.dismiss() to close the prgoress dialog.
here you can see an example:
the progressdialog is created and displayed and a thread is called to run a heavy calculation:
#Override
public void onClick(View v) {
pd = ProgressDialog.show(lexs, "Search", "Searching...", true, false);
Search search = new Search( ... );
SearchThread searchThread = new SearchThread(search);
searchThread.start();
}
and here the thread:
private class SearchThread extends Thread {
private Search search;
public SearchThread(Search search) {
this.search = search;
}
#Override
public void run() {
search.search();
handler.sendEmptyMessage(0);
}
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
displaySearchResults(search);
pd.dismiss();
}
};
}
I am giving you a solution for it,
try this...
First define the Progress Dialog in the Activity before onCreate() method
private ProgressDialog progressDialog;
Now in the onCreate method you might have the Any button click on which you will change the Activity on any action. Just set the Progress Bar there.
progressDialog = ProgressDialog.show(FoodDriveModule.this, "", "Loading...");
Now use thread to handle the Progress Bar to Display and hide
new Thread()
{
public void run()
{
try
{
sleep(1500);
// do the background process or any work that takes time to see progress dialog
}
catch (Exception e)
{
Log.e("tag",e.getMessage());
}
// dismiss the progress dialog
progressDialog.dismiss();
}
}.start();
That is all!
Progress Dialog doesn't show because you have to use a separated thread. The best practices in Android is to use AsyncTask ( highly recommended ).
See also this answer.
This is also possible by using AsyncTask. This class creates a thread for you. You should subclass it and fill in the doInBackground(...) method.