I'm developing an Android 3.1 application.
I want to execute an AsyncTask after activity is shown. I want to show something to user before execute AsyncTask.
I've read that it is not recommend to execute AsyncTask on onCreate().
Where I have to execute AsyncTask on onStart() or onResume()?
I want to left enough time to show activity before execute it.
onCreate(), onStart() and onResume() are lifecycle methods called by the operating system and shouldn't be called directly. You can however override them to have your code executed at these stages of the activities lifecycle:
However, if you want your AsyncTask to start after all of your Views have been inflated and drawn to the screen then you need to put the code in this:
toReturn.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
toReturn.getViewTreeObserver().removeGlobalOnLayoutListener(this);
// asyncTask.execute();
}
});
In the above example toReturn is a view in your onCreate() method. It can be any view you like.
This pulls a ViewTreeObserver from the View and add's a listener to it which will be called when the view has finished being drawn to the screen. It's important you keep the "removeGlobalOnLayoutListener()` line in as this will stop the code firing every time the View is drawn.
Answer is in onResume()
I hade same requirement in my activity where i need to show some list with other buttons and images..
List were getting data from server so used AsyncTask for that..
But before that required to show empty listview and other part of the screen..
so first when it goes to onCreate() I set empty arraylist to listview's adapter then in onResume() call the Asynctask and in that task fill the ArrayList and call adapter.notifyDataSetChanged()
Then another problem occure..when i go to next activity and come back it always call the asynctask even if i dont require..
So had put some condition like if(arrayList.size()==0) then call asynctask else dont.
You can put yur code in the onWindowsFocusChanged method. You can use a thread inside it to manage the timer to start your specific asynctask.
Be aware that this would be performed each time your activity have the focus, not only the first time you launch your activity (I don't know if this could be a problem for you).
implement a View object and override the onDraw().
that way you'll know exactly when the first screen is visible to the user
Related
I'm using rxjava and rxandroid. In my presenter i have used
Observable.timer(10, TimeUnit.SECONDS);
And I would like to save time on screen orientation change. For example timer starts and after 3 seconds user is changing screen orientation, and timer starts again but from 0 for 10 seconds, but it needs to run for 7 remaining seconds.
Do you know any solution?
When you orientate your device, it recall onCreate() method of your activity and redraw your views. For this you can create a helper fragment and put your operations in that fragment. Put this line setRetainInstance(true); in onCreate() method. Then, do your operations onAsyncTask. If you wand display each second of timer in your screen, then call onProgressUpdate() method of your AsyncTask class. Then, create an interface, withProgress callback and put this callback in onProgressUpdate() method. Then you can handle this operations via implementing that interface which you created in your fragment. I have simple repository in github which can help you. Enjoy. This article also can help you: Enjoy.
When are the view's 'killed' and no more exist in Android ?
For example, suppose I have an asynctask and I run some network related stuff in the doInBackground() method. Then, I need to update my UI views in the onPostExecute() method.
Assume my doInBackground() took a while and while it was being processed the user moved back or even pressed the home button. The task will continue because doInBackground runs on a seperate thread, however, once it is finished and onPostExecute is called to update the views, the views might not be there.
Even if the activity is not visible (either gone to home screen, or another activity), what happens when the views try to get accessed and modifed ? How long do they stay in the 'heap/memory/whatever', do they get garbage collected after onDestroy ? or they stay around after that ?
I know a way to not get into this hastle is to use a switch that gets turned on and off inside onResume and onStop and check it before updating the views in onPostExecute, but I am unsure if this is solid approach applied in the android apps ? if not, what is the suggested way ?
A view inside an activity can be considered like any other object within the activity class. It will stay in the memory as long as it is referenced by the some other object. This object could be another view or activity. This means the view will be gone if:
1) The activity or the parent view remove it removeView() from the view tree thus no one keeps a reference to it.
2) The activity or parent view that contain the view are destroyed/gone from the memory.
If the activity is not visible (either gone to home screen, or another
activity), what happens when the views try to get accessed and modifed
? How long do they stay in the 'heap/memory/whatever', do they get
garbage collected after onDestroy ? or they stay around after that ?
You can access the view, as long as your activity is available. And you can find more about that by reading the Activity Lifecycle
When you try to access a view that is gone from the memory, you will get a NullPointerException. The simple & solid way how you can handle onPostExecute is by checking for null before updating, example:
// inside onPostExecute
if(textView != null) {
textView.setText("Background Method Finished");
}
The advantage of this approach is:
1) You do not have to explicitly keep track of show/hide.
2) Sometimes, view is not on the screen does not mean that it gone from the memory. For example, let say your AsyncTask finishes while your activity is paused/stopped not destroyed. In this case, you can still update the view, so that when the activity is resumed the update is visible and is not lost.
Cancel async task when user leave from that activity. After cancelled task, onPostExecute will not called and capture cancel event in onCanceled event in async task class.
You have many ways
1.You can cancel the asynctask
2.You can kill the process,so there will be nothing in the menory or heap.
My Problem: Is it possible to prevent an activity to call OnResume() when it is being created? As I saw after the OnCreate() and onStart() method runs, the next one is the onResume(), although I only want to have it when I resume the activity from the paused state.
Why do I need this: I launch my activity (FragmentActivity, so lets say OnPostResume() ) starting with a thread which takes about 2-3s to be ready getting data from an external database. After the thread is done, I call a method which needs these data and I want to call it everytime that activity gets visible. The thread runs only when the FragmentActivity is created (onCreate()), and I cannot put the method into the onResume() because onResume() would be running way before the thread would finish its task. So it would receive not-ready data.
Anyone has a better idea?
Not sure of the exact application of this but I'll make a suggestion.
If you use an AsyncTask, you can send it off to get the data you need and in the onPostExcecute() method you can call your method that requires the data or update the view as needed. (It runs on the UI thread)
If you happen to already have the data you need in certain scenarios you could also bypass the AsyncTask and directly update the view.
This AsyncTask can be triggered in the onResume() method.
If I'm missing something, please let me know and I can adjust my suggestion.
I didn't understand the purpose of this, but here's a possible solution:
If you only wish to get the even of onResume on states that didn't have the onCreate before, just use a flag.
In the onCreate, set it to true, in the onResume check the flag (and also set it to false). if it was true, it means the onCreate was called before.
I personally would prefer to check if the result available, rather than always executing the getter-code in onResume. If the user somehow resumes your activity before the background thread is finished, you'd have a call on onResume, but don't want to display a result.
Maybe it would be a good idea to calculate/fetch the values in the thread, and let the thread return immediately (and cause the values to get filled in) if the values are already cached somewhere. That way you'd only have one entry point (the thread) for updating your UI instead of two (the thread and the onResume method).
I have a Async Task that creates a HashMap to create a Adapter to populate ListView. I have a progress dialog that shows during doInBackground method.In onPostExecute() method, I dismiss the progress dialog and call a method that populates my listview with the list of items saved in doInBackground method.
This works fine. But I noticed something strange:
The issue I see is, if I lock the screen when the progress dialog is about to be dismissed (in onPostExecute), the listview does not display, even though it has non-empty items in it. I verified it in logcat messages and when I debugged.
Is there a possibility that a screen lock (I do this my pressing power button once) blocking UI thread? How can I resolve the issue and make sure ListView displays its items?
Code for onResume():
#Override
protected void onResume(){
super.onResume();
if(MyAdapter !=null){
pull_listView.setAdapter(MyAdapter);//pull_listView is listview
MyAdapter.notifyDataSetChanged();//MyAdapter is the adapter
}
}
This situation illustrates the downside of using AsyncTask to do background processing. In some cases, an IntentService may be a better choice, especially if you think the background work is going to take some time. An AsyncTask ties the background work to the current Activity, while an IntentService is completely decoupled.
The Android training class Running in a Background Service shows you how to set up an IntentService, request work, and notify your Activity when the work is done. Passing data from the IntentService to the Activity is a bit more complicated, but there are options.
onStop() will be called when your screen goes out as per the Activity Lifecycle. You could override onStart() or onResume() and put a check in there to see if your data has been populated. If not, populate. You may even want to overide 'onStop()' to save data if the screen goes out.
Edit
In this particular situation, I would think onResume() or onStart() would be fine but onResume() is usually the safest because it is guaranteed to get called before the Activity is shown as illistrated in the link I gave. What kiind of a check you want to use is up to you and depends on how you handle evrything. However, if your AsyncTask is an inner class of your Activity class the you could simply create a boolean member variable, say boolean isDone=false; change this to true in your doInBackground() or onPostExecute() then your onResume() knows the data Is loaded. If its false then you can try to get data again. Hope this makes sense and can help
I am using ImageView in my example. I set Images as background of imageview in xml. Now I want to change this image background of Imageview at run time.
this is my java code.
changeImage()
{
ImageView imgview=(ImageView)findViewById(R.id.imageView1);
imgview.setImageResource(R.drawable.headerhindi);
}
I am calling this method from onCreate(). First time my method works fine. but when I redirect again to my activity onCreate() using startActivity(myActivityIntent); this method does not works properly means Images does not change according to this method. By default images which is set in xml is shown.
Please help me to find out the solution.
Thank you in advance.
Try moving the call to changeImage() to onResume().
I haven't tested it, but I have a feeling that what's happening is that when you call startActivity() to start the activity again, the activity was not destroyed yet so onCreate() is not called again as per the activity lifecycle:
http://developer.android.com/images/activity_lifecycle.png. Just a hunch though.
How to you redirect to your activity onCreate ?
If your activity was already running, it skips onCreate and goes directly to the Started state.
You probably want to move your changeImage() to the onStart() method which get called on creation and resuming.
You can see full explanations here: Managing the Activity Lifecycle
※ The main difference for you between onStart() and onResume() would be that onStart() is called before the activity becomes visible while onResume() is called after.