I am having a Fragment in which I have used Handler which sends a request after each 60 seconds. This is working fine till I am on the same Fragment.
But when I redirect to other Activity or Fragment in some other Activity, the same Handler is working there also, I want this Handler to work only on that Fragment and want to remove it when I am on some other Activity or Fragment.
I have also used handler.removeCallbacks(runnableCode); on onDetach function of that fragment.
Please help me if you have any idea here, thank you so much in advanced.
You should not call removeCallbacks at onDetach. Your Fragment can be invisible but still not destroyed (paused). notice that onDetach is called after onDestroy. According to the docs:
Called when the fragment is no longer attached to its activity. This
is called after {#link #onDestroy()}.
Use removeCallbacks on onPause instead.
If you want more info then please add your code and we will see why it's not working (but after changing the call to removeCallbacks)
Related
Could anyone explain what does exactly happens (lifecycle of Asynctask) if for example I have and Activity with a Fragment and from this Fragment I execute an Asynctask where on the onPreExecute I start displaying a ProgressDialog and at some point I close the app while the Asynctask is still running?
As far as I've checked the Fragment doesn't call onDetach nor onDestroy and the Asynctask doesn't reach the onPostExecute method or onCancelled
If i am not wrong you are familiar with lifecycle of an AsyncTask. If not, refer
https://developer.android.com/reference/android/os/AsyncTask.html
To answer why onPostExecute method is not called when we exit the app while the progress bar is still running, I would say it is because, AT holds a reference to the Activity/Context which would be destroyed by the time progress bar decides it's job is done(bg task/thread).
Very useful blog on how to handle ATs wrt fragments and activities by Alex Lockwood.
http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html
Have you set setRetainInstance(true) in your fragment, whenever you start asynctask inside a fragment with setRetainInstance as true the task will continue to run in background without interrupt which is not in the case of an activity
Please ensure that AsyncTask.doInBackground() has been completed. Or, what is more possible, your main thread is stuck somewhere as AsyncTask.onPostExecute() must be executed in main thread.
In the scenario you are speaking about, the Fragment methods "onPause()" and "onStop()" will be called (besides of the ones of the Activity which contains the given Fragment).
As those methods are being called, you should react according to what you want to do in the AsyncTask.
If that's not the case, refer to the link given by #stack_ved.
Anyway, if you want to do any kind of load inside a Fragment, I strongly recommend you to use "Loaders" or "AsyncTaskLoader".
https://developer.android.com/reference/android/content/AsyncTaskLoader.html
I have a quick question.
If I add a Fragment by:
getFragmentManager().beginTransaction().add(...)
will it be always accessible by:
getFragmentManager().findFragmentByTag(...)
assuming I will never call beginTransaction().remove ?
(I will only use hide() and show() transactions to manipulate its visibility)
I don't see why not , according to the documentation , it will be accessible , however make sure you don't call .replace() either.
Because .replace() is a like a sequence of .remove().add()
Also transactions do not get added to the back stack by default. You can:
transition.addToBackStack("TAG");
After that you can use its identifier without problem, if you want to refer to it later.
Sure, Fragment is always accessible as long as it is attached to the activity. Fragment gets detached as soon as onDetach is called.
onDetach Called when the fragment is no longer attached to its activity. This is called after onDestroy(), except in the cases where the fragment instance is retained across Activity re-creation (see setRetainInstance(boolean)), in which case it is called after onStop().
For visibility, you are using hide() and show(),
hide() and show() is only relevant for fragments which are already attached to activity.
In short, onDetach never gets called during hide() and show().A attached fragment never get detached from the activity during hide() and show().So ,it will be accessible.
I have thinking some time about this. I have an FragmentActivity in wich I have a FrameLayout and some Fragments change there. Each fragment has different layout and launches different asynctask. My question is :
Where is the best place, I mean best fragment state, to call asynctask ? I mean like I have some textviews in fragment layout and I want them to display text values based on asynctask result. Should I call the asynctask in onCreateView or somewhere else ? Making the call in onCreateView would invoke the asynctask more times as the orientation would change, as I am aware of. So what is the best practice for fragments with asynctask ?
Better to use AsyncTaskLoader instead AsyncTask with fragments
When you create the Asynctask in onCreate it gets called only when the fragment is created. When you call it in onResume it gets called even after the user returns gets a phone message. So it depends on how up to date you want the data.
You could even call it in onViewCreated but it really is up to you. You can also call it in the application object so the asynctask is executed only when the user starts the app.
I have a fragment that does a startActivityForResult() call in OnCreateView if there is no internet. In the NoInternet Activity there is a retry button that finish()es the activity (So I can supposedly check for connection again). When the activity finishes, OnCreateView of the fragment is never called (because OnCreate() of the host Activity is never called) and I end up not cheking if there is internet again.
Now a simple way around this is to check if there is internet in the OnStart() of the main activity (that hosts the fragment).
But I was wondering: Is there a way to force OnCreateView after finish()ing an Activity that was started with startActivityForResult()?
I think your problem is the understanding of the lifecycle of Fragments. If you call startActivityForResult() on a Fragment, it will be executed on the fragment's containing Activity. Now the Activity goes in the Paused and then Stopped state and also will the Fragment. If you finish the "ResultActivity" the states Started and Resumed will be passed through on the Activity and the Fragment.
So, how you said already, just move your connection checking and your startActivityForResult() call into onStart().
There is no need to create a new view for Fragment. If you want to alter the View programmetically you can do that in onStart() and onResume().
But don't break the lifecycle just for a method call which could be easiely invoked in another callback.
I'm not sure exactly how you're using the fragments/activities in question but it sounds like the fragment view of the main activity is not being destroyed when you call startActivityForResult() for the new activity. This behavior is normal under some cases which means which your fragment would only be stopped or paused. So, doing your network check in the OnStart() or OnResume() would be the correct usage.
Whats the recommaned approach to notifying the hosting activity of a fragment that performs some background processing, that its done. Assuming that the fragments are running some threads that are performing work outside of the main looper.
A simple callback won't do since:
The Activity could be detached due to screen rotation which would lead into a NullPointerException.
Polling from within the activity is just dumb
Only calling the activity once if attached and let the activity check after each onCreate call (i.e. due to screen rotation).
What I currently do but it seems wrong: Whenever the Fragment gets attached, it will check if the work is done and notify the activity via callback. If the fragment finishes the work it will also callback the activity (if attached).
Why I think is is wrong? Because I have some really ugly methods that check if the fragment is attached and also if the work is done in order to maybe call the callback. This becomes very stupid when an exception is raised during performing some work in the fragment and the activity is detached. If android decides to call onSaveInstance in the same moment I will have to put the Exception into the Bundle and deliver it later when the Activity and fragment is recreated from the saved state. Additionally I can run into a situation where a activity will received the same callback twice (once from checking the fragment and the second time when the fragments gets attached; this could happen when the application got saved and restored)
This generates so much code that, in my optinion, could be much more clear if activites won't get detached. That is why I hope I'm doing something wrong and hope someone will provide me with a better solution.
I would say you should use a service for your background processing but if you've chosen a fragment for a specific reason you can stick with that. The way you should notify the activity from either a fragment or a service that might have a different lifecycle from the activity would be through a BroadcastReceiver. With this method the activity can register and unregister a BroadcastReceiver during its own lifecycle callback. From the fragment or service you just send the broadcast and forget about it. If an activity is listening for the broadcast it will receive it, if not nothing will happen.