When my Android app is starting up needs to load a lot of data from the database during onCreate in the firstly loaded activity. I would like to show a ProgressDialog for that. ProgressDialog however can't be shown in the main thread, so one must use AsyncTask or new Thread. But that also means, that the activity continues to be initialized as the main thread goes on.
Basically, I need to show the ProgressDialog or a kind of its equivalent while processing in the main thread (not in AsyncTask).
Is there a way to do it?
ProgressDialog however can't be shown in the main thread, so one must use AsyncTask or new Thread.
How do you come to this conclusion? ALL UI stuff is shown in the UI Thread, thus also the ProgressDialog. It needs to be created and invoked inside the UI Thread to work or else your App crashes.
First you need to check on onCreate() if your stuff is already loaded and if not, show a ProgressDialog, load stuff in the background and then do a post in the UI Thread to dismiss the ProgressDialog and show the results.
That's how it usually works.
The Main/UI Thread is responsible for drawing the UI, and hence, the ProgressDialog itself . So you can not block it and hope that he is going to draw the UI. You should move the initialization stuff inside AsyncTask's doInBackgroud, and move on with the other suff after onPostExecuted is called
You should load the the data with the Thread (ASyncTask) you should display your ProgressDialog with "onPreExecute()" update it with "onProgressUpdate()" and finish the dialog with "onPostExecute()" all of them is running on UI thread already.
You will never be able to show progress because your view of activity have not created, because you read from database in onCreate methode after reading the database onCreate method finshes and now your view inflate and so on . . .
Related
I am Loading all the data on splash Activity and when all calls return I want to populate another activity but keeping the splash activity until the main activity is populated.
I tried using AsyncTask but still not working, I have a delay when switching from the splash activity to the main activity.
I expect to go from splash activity to another Activity without Delay and the activity to be populated.
There are 2 solutions to your problem:
Disable animation when starting your MainActivity and try to minimize the consuming tasks in that activity.
Combine SplashScreen to your MainActivity as a View, after finishing loading all necessary tasks, just hide that SplashScreen View
You have to upload the part of your code where you are calling the intent to the other activity before we can actually understand what is wrong. However, ensure you are not doing too much activity on the application main thread since this can make your UI unresponsive and make the app slow. See this for reference =>
https://medium.com/#yossisegev/understanding-activity-runonuithread-e102d388fe93
https://developer.android.com/topic/performance/threads
start new Android Activity is so slow
You can also make your app call the new activity on a separate thread to ensure all the data it needs to pass to the other activity is received before navigating to the new activity and also ensure you are not doing too many resource consuming task in the onCreate method of the new activity you are calling
So I want my main UI is display before I launch a bunch of asynctasks. However, in debug mode after the line setcontentview is called, the layout does not show up on the screen. How do I get it to show up before I run the multiple threads?
The example is below
SetContentView(R.layout.main)
//loop and run multiple asynctask threads
setContentView() is called in the main UI thread. That means that if you are debugging, you block the UI thread and no UI can be shown until onCreate() has finished. Move your breakpoint inside doInBackground() of the AsyncTask and you will see the UI.
So here's what happening: I'm using the runOnUiThread() method to change an Image View from another class when that class receives a message from another phone. I'm calling it by using mainclass.runOnUiThread(new Runnable...) and so on. It works the first time the application is run, but when I hit the back button to exit the application, and then launch the application again, the Image View no longer updates. The logs I took shows me that everything is fine and being run, but the Image View doesn't change. I don't get any errors and it doesn't crash when I run the application, it just doesn't update the Image View. Any idea what might be causing this?
Edit*: So this is what i'm actually using to change the imageView in a class that doesn't extend Activity
peerActivity.runOnUiThread(
new Runnable(){
#Override
public void run() {
Log.v("Thread#", "Thread is running");
Log.v("Thread#2", decodedImage.toString());
// TODO Auto-generated method stub
peerActivity.ivPhoto.setImageBitmap(decodedImage);
Log.v("Thread#3", "Past UI Change");
}
});
Where peerActivity holds the other class reference and ivPHoto is the Image View. What I think I need to do is find a way to kill that thread when the program closes (when I go into the program manager, it still has the Force Close button available). Is there any way to do this?
Edit2*: So I tried a bunch of different approaches to working on the UI Thread and they all give me the same result: The program works perfectly the first time its run but when I hit the back button and close it and the re-open it, the Image View no longer updates. If I force close the app, it works fine again until I close it and re-open it.
Try using View.post(...) instead.
I use new Handler(Looper.getMainLooper()).post(...);
You can even create this from a background thread.
It looks like your Runnable is closing over a reference to your activity. When you press back and then start your activity again, your old activity is destroyed and a new instance is created. Your background thread continues to make changes to the original activity, which no longer exists, therefore making changes to its views has no effect.
You need to either stop the updating thread when the actiivty is paused or stopped as appropriate and restart it when the activty is resumed or started (again, as appropriate) and make sure that you are always updating the activty that is actually visible.
I am new in android and java. I am in a trouble in implementing progress dialog correctly.
I have a code like this
ProgressDialog dialog= new ProgressDialog(Main.this);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setMax(100);
dialog.show();
MY METHOD WHICH GRABS DATA FROM INTERNET;
dialog.dissmiss();
but by implementing this, my method runs well but no progress dialog is visible, again when i comment out the dismiss method, the dialog doesnt stop and i had to force close the app,then how to use this dialog? in aditional dont want to bring any thread here, is there any way to use dialog without any thread? Thanks
Problem here is that any long running tasks such as fetching data from the Internet must be run inside a separate thread, otherwise you're likely to get an ANR if your code runs for more then 5 seconds. The ideal solution in my opinion is to implement an AsyncTask: it lets you run tasks in a separate thread and helps you easily update your UI thread, showing ProgressDialogs or ProgressBars to let your users know that your app is currently busy. Simply place all your ProgressDialog initialization code inside the onPreExecute() method of the AsyncTask, and the dialog.dismiss() call to onPostExecute(). Hope this helps.
Yes, you no need to use Thread class. You can use AsyncTask instead. Start the progress dialog when you call the AsyncTask, dismiss it in the postExecute method.
I personally prefer AsyncTask for progress dialog.
In your onPreExecute, create your above code. In doInBackground, do your background tasks and in onPostExecute display an alertdialog saying work done !
When the user switches from tab A to tab B it takes a long time (6 seconds), so I put in a progress dialog to let the user know that the app is working on it. The timeline is as follows:
Activity B onCreate - creates ProgressDialog and puts long tasks in a background Thread.
Activity B onStart
Activity B onResume
Activity B appears on the screen
This all works great with one "minor" snafu- the app intermittently crashes because the onResume function references something that is created by the background Thread. It is, in other words, a classic race condition.
To fix the race condition I did a "join" on the thread right before the reference in onResume, but that makes the progress dialog not show up until the background thread is done (i.e. it shows up for a split second and then goes away) and the app acts like it is hung while the background thread is working. Apparently the progress dialog cannot show up until onResume completes.
My question is this: how can I get the ProgressDialog to show up without crashing the program? Or do I need to either get the offending reference out of onResume or live with the app acting hung?
I ended up using a kludgey solution wherein the onResume function waits for the intermediate result that it needs, but not for the entire background thread to finish. This is ugly, I know, but it appears to work.
The better long term solution, I believe, is to separate the creation of the needed object from the long initialization steps that it does when it is created. The timeline would then be:
onCreate
Create object
Create progress dialog
Create background thread, have it do long initialization of object.
onStart
onResume (with no check/sleep loop).
A dirty solution would be to have one ProgressDialog for steps 1 and 2, and then create a second identical-looking one for steps 3 and 4.
Are you using Threading as provided by the Java platform or are you using the Android convenience classes?
I am referring to AsyncTask. More than likely you are running in to issues with your Runnables posting at inconvenient times. The AsyncTask class packages up these features nicely. Subclass AsyncTask, specifying the types for your params, progress, and result. Then hide your dialog in the onPostExecute method, while you perform background work in the doInBackground method.
Sample code:
AsyncTask<Void, Void, Void> parseTask = new AsyncTask<Void, Void, Void>() {
#Override
protected void onPostExecute(Void result) {
// Dismiss the progress dialog
dismissDialog(PROGRESS_DIALOG);
}
#Override
protected Void doInBackground(Void... params) {
// Do background work
return null;
}
};
// Start the background thread
parseTask.execute();
Taken from a live code base. Also don't feel too bad, concurrent programming is easily one of the more difficult systems to program. It is promising that you were able to recognize and identify the race condition.