Hi i have an AsyncTask in my application called in OnCreate() that retrieve some data over the web and display an indeterminate progress bar while downloading.
The problem is when i start the app the screen remain blank until the AsyncTask is finished.
The code is something like that.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
loadData();
//Several UI Code
startAsyncTasks();
}
private void startAsyncTasks(){
new ConnectingTask().execute();
}
OnCreate() is executed before the Activity is being shown on the screen, so the whole data download process executes before showing the activity.
Solution could be to start AsyncTask in OnStart() method instead of in OnCreate() (also overriden). OnStart() is executed while activity is going to be shown on the screen (see activity lifecycle).
This is the case I have implemented in my app and it works. You should show a progress dialog in OnStart() method, and update and dismiss it in AsyncTask in proper moments.
This is how it looks in my app:
AsyncTask is started in activity OnStart() along with showing dialog box
Data is being downloaded in inner class extending AsyncTask
After data is downloaded the dialog box is dismissed and further data processing initialized (OnPostExecute())
The drawback could be that OnStart() is called on the first activity call, but also after restoring it (for example after minimizing the application). So AsyncTask can be executed few times in opposite to OnCreate(), that is called only once - when activity is created (not when it is restored).
There can also be some issues if You do the jUnit test of such activity with dialog in AsyncTask - let me know if You do - will post some solution
Related
I want to specify an activity to be the loading activity for my app for some async Tasks .
it will be launched during in preExecute and will be finished in postExecute how to do that ?
#Override
protected void onPreExecute()
{
startActivity(new Intent(SearchActivity.this,LoadingActivity.class));
}
#Override
protected void onPostExecute(String result)
{
// i want to finish loading activity here.
}
That's just not how Android works.
There is always one Activity active at a time, and when you start an AsyncTask, you do so in the context of the current Activity.
So, while you technically could start an activity from the AsyncTask, it's parent context (the Activity that started the AsyncTask) would become inactive. The AsyncTask would continue to run (this is actually a big problem with AsyncTasks), but would likely crash - and even if not, the behavior would be undefined.
Shubham Nandanwar's answer looks like it should work, but is not the correct way to approach this. You should reconsider what you are trying to do in the context of the way that Activities and their lifecycles are supposed to work.
I'd suggest simply launching the Activity that you desire, and then use an AsyncTask in that activity to do whatever work needs to be done, and finish the activity from the activity itself when the work is done.
Better yet, find a better way to do background processing (e.g. RxJava), and do away with the AsyncTask.
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 working on an android app where i need to download some images and start a slide show.
For downloading the images i am using a AsynTask, as soon as the images are downloaded i am using an handler to start the slide show. But during orientation change i am not able to control the handler. Because the handler object is defined with AsyncTask class.
The below is the rough scenario of what i have done:
Class A extends Activity
Class B async = new ClassB(this);
async.execute();
Class B extends AsyncTask implements OnPageChangeListener, OnTouchListener
onPreExecute() -------Nothing in this method
doInBackground -------I am downloading the images here
onPostExecute ---------Handler starts here and runs for every 5 seconds for implementing Slide Show
Now the Problem:
During orientation change i have made sure that AsyncTask is called only once or else it downloads the images again, because of this the handler is not running during orientation change.
The first handler object which was started, it keeps running but the changes does not reflect on the screen.
I was thinking of implementing in a way that the images are downloaded by using the AsyncTask and once the downloading is done, ClassA should gain focus and handler should be implemented in ClassA(only when images are downloaded).
The Interface class naming is according to my case. Please adjust it according to your rquirments. ArtikelDetailsDataLoader my Async task. Which tell my activity that details are loaded.
in your Class B
public interface OndetailsLoadInterface {
public void onDetailsLoad(ArtikelDetailsInfo artikelDetails);
}
OndetailsLoadInterface detailsLoaderInterface;
public void setOnDetailsLoadListener(OndetailsLoadInterface detailsLoader) {
detailsLoaderInterface = detailsLoader;
}
and in onPostExecute
detailsLoaderInterface.onDetailsLoad(artikelDetails);
and in class A
ArtikelDetailsDataLoader mLoader = new ArtikelDetailsDataLoader(
items.get(position).getId(), mContext);
mLoader.setOnDetailsLoadListener(mLoaderLisnter);
and
OndetailsLoadInterface mLoaderLisnter = new OndetailsLoadInterface() {
#Override
public void onDetailsLoad(ArtikelDetailsInfo artikelDetails) {
//do slide show
}
};
Just make a method in your Activity called startSlideShow(position) that you call from your onPostExecute() method, with startSlideShow(0).
On orientation change save your current slide show position, and your downloaded images, and then in your onCreate(Bundle savedInstance) then start the slideshow from the previous position using startSlideShow(restoredPosition);.
If your problem is caused by the Activity restarting when orientation changes, have you considered setting android:configChanges="orientation" in your AndroidManifest.xml entry for the activity, which should prevent the restarts?
Then, if you need to perform any updates to the UI (e.g. switching to a different layout), you can handle onConfigurationChanged(Configuration) and implement it yourself.
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
I wrote a script to simulate the user actions. The workflow is, for example, first tap an icon, launch an activity. Then do other actions.
The question is , I don't know the exact time that the activity launched completely. At present, I use sleep to make my script wait.
Is there any way to know when an activity launched completely?
I dont know what exactly you want to do when the activity started. But normally everyones requirement is to find width of a view or something to do with the UI. The thing is, onCreate is called before the UI is drawn so nothing related to the UI that involves measuring can be done here. For that we can use a global layout listener.
ViewTreeObserver vto = outerLayout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
outerLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
//This is executed once the layout is drawn. AFAIK this is as close as it gets
to when the activity is started.
}
});
Is your final task is to run something after activity is launched... do this
First method called from activity is onCreate() , Hence we can say completing the onCreate() system calls onStart() which calls onResume() method... as onResume() completes you can say your activity is launched properly...
If you are not going to override onStart() or onResume() what I am going to describe can be written as last statements of onCreate(). That's I usually do when I don't need onStart() or onResume().
You can create an object of Handler. Like
Handler handler = new Handler();
Handler has a method postDelayed() that is called some times after the creating and launching is finished.
call it like
handler.postDelayed(runnable,timeInMilliSeconds);
after all the processes finish, application will wait for timeInMilliSecondsms to start the process defined in run method of runnable provided in postDelayed .....
Thus
If your task is to know when the launching is finished the answer is: at the end of onResume() called from your onStart() ....
If you want to perform some action use handler.PostDelayed() method and keep timeInMilliSeconds very low... [between 1 to 10].