ListFragment and onActivityCreated called twice - android

i have a listFragment this is my onActivityCreated:
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
utenti=savedInstanceState.getParcelableArrayList("array");
}else{
threadutenti= (GetUtenti) new GetUtenti(this.getActivity(), utenti).execute();
}
When i rotate my device i have first savedInstanceState non null (i got it) but after onActivityCreated is called with onActivityCreated null!! why? i want get my object utenti on ListFragment and not on my activity..

This can happen if you're always creating a new fragment in your Activity#onCreate() callback.
If it's true, check this answer. Your Fragment#onActivityCreated will be called twice:
First time triggered by FragmentActivity#onStart's call to mFragments.dispatchActivityCreated(). It will pass the saved instance.
Second time triggered by FragmentActivity#onStart's call to mFragments.execPendingActions(). This time without saved instance (since it is being called in response to new Fragment addition).

Related

Viewpager fragment reference to new copy after activity restore

When my activity containing viewpager is killed by system in background and then restores its state, fragments are correctly created and viewpager adapter can also point to them correctly.
But when I get a fragment reference and try to access its fields, they are all null (checked by using breakpoint).
I checked this by placing breakpoints in fragment onCreateView() and in my activity button's clickListener.
((WelcomeFragment)homeActivityFragmentPageAdapter.getItem(POSITION_HOME)).setdata(myData);
Now this method will through null pointer exception since setdata(data) is internally accessing arraylist field of fragment.
This creates a problem for me since, my activity has to continuously feed network data to the fragment by calling its public method (as suggested by documentation).
How to insure that after state restored; correct instance is pointed in my activity.
Try to use instantiateItem adapter method instead getItem.
((WelcomeFragment)homeActivityFragmentPageAdapter.instantiateItem(mViewPager, POSITION_HOME)).setdata(myData);
Method getItem is overrided method, and common use is creation of child fragments.
EDIT:
In case of the question's scenario, you also need to store the state of FragmentStatePagerAdapter manually:
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState
.putParcelable("pages",homeActivityFragmentPageAdapter.saveState());
super.onSaveInstanceState(savedInstanceState);
}
Then you can retrieve the state in oncreate:
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
homeActivityFragmentPageAdapter.restoreState(savedInstanceState.getParcelable("pages"),this.getClassLoader());
welcomeFragment = (WelcomeFragment) homeActivityFragmentPageAdapter.instantiateItem(mViewPager, POSITION_HOME);
}
else { //simply create a new instance here}
homeActivityFragmentPageAdapter.addFragmentToAdapter(welcomeFragment);
homeActivityFragmentPageAdapter.notifyDataSetChanged();
}

Android: on screen rotation what should Fragment's onCreate() and onCreateView() do

In my activity I have a check for savedInstanceState, making sure I am not creating multiple fragments
But my question is should I have similar checks in Fragment's onCreate() and onCreateView()
Because when I rotate screen Fragment's onCreate() and onCreateView() are called everytime.
Question is, Is it OK for these 2 methods to re-do there job after everyscreen rotation or they should have a savedInstanceState check as well.
Right now my onCreate() makes a service call and onCreateView inflates a view (Recyclerview)
When an activity or Fragment is recreated, the onCreate() method is first fired, followed by the onRestoreInstanceState() method, which enables you to retrieve the state that you savedpreviously in the onSaveInstanceState() method through the Bundle object in its argument:
# Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
//---retrieve the information persisted earlier---
String ID = savedInstanceState.getString(“ID”);
}

Bundle savedInstanceState is always null

I have two different activities, in the first one I enter some info into some EditTexts, I then go to the second activity, but when I return, the text that was on EditTexts in the first activity are gone.
Here is the OnCreate() for the first activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_frm_recetas);
txtClient = (EditText) findViewById(R.id.txtNombreCliente);
if(savedInstanceState != null){
String client = savedInstanceState.getString("Client");
txtClient.setText(client);
}
}
I'm using the onSaveInstanceState method to save the info
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
String x = txtClient.getText().toString();
savedInstanceState.putString("Client", x);
super.onSaveInstanceState(savedInstanceState);
}
When doing a debug, I can see the savedInstanceState Bundle has indeed been filled in the onSaveInstanceState method, but in the OnCreate in shows null.
Maybe I have to add something in the second activity? I currently don't have anything in there other than a button that takes me back to the first activity.
You need to call super.onSaveInstanceState(savedInstanceState); as the first line in onSaveInstanceState method.
Next you need to put
if(savedInstanceState != null) {
String client = savedInstanceState.getString("Client");
txtClient.setText(client);
}
into the onRestoreInstanceState method. onCreate is only called when re-drawing the app.
It shows null because onCreate is called only when that activity is first created, when you return back from the second activity, it resumes your first activity..try showing it on onResume() method
My guess is that the first activity hasn't been destroyed, so onCreate is never called when you navigate back to first activity
I guess onCreate is called when aactivity is going to load into memory, and at that time activity does not contain any thing . thats why it always return null.
to save data you have onsaveinstance method and to restore you have onrestoreinstance method.
onSaveInstanceState() is a method used to store data before pausing the activity.
onRestoreInstanceState() is method used to retrieve that data back.

Bundle in onActivityCreated() returns null, even after setting values in onSaveInstanceState()

In a application whenever a fragment loses focus (i.e. another activity / fragment is opened over it), it's onSaveInstanceState() is called.
Same is mentioned in developers guide.
I'm trying to use this approch to maintain the state of my fragment whenever it is resumed.
My intention was to call this bundle in onActivityCreated(), when the fragment is resumed.
Although onSaveInstanceState is called before fragment losing focus.
But, when onActivityCreated() is called it recives the Bundle savedInstanceState as null.
How can I fetch the data from the bundle.
Code:
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
MyListAdapter adapter = new MyListAdapter(getActivity(),
R.layout.my_row, titles, icons, this);
setListAdapter(adapter);
if (savedInstanceState != null) {
// Never goes inside this condiiton.
// Restore last state for checked position.
mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("curChoice", mCurCheckPosition);
}
Then it means that your activity and fragment were just paused and did not have to save their instance state (onSaveInstanceState() is not necessarily called).
If you want to make sure onSaveInstanceState() is called, select "Don't keep activities" in the device's developer settings. Then each time an activity is paused, the system kills it forcing the call to onSaveInstanceState() (except when you just press back of course)

How does retaining fragment instance with setRetainInstance(true) work?

I have a fragment without view which I use to host an AsyncTask. I want to retain the fragment object during configuration changes (eg. orientation change). To my understanding using setRetainInstance(true) in the onCreate() method of the fragment should be enough. But here is my problem:
First of let me post some code I'm using.
My activity uses this in its onCreate() method
protected void onCreate(Bundle savedState)
{
super.onCreate(savedState);
/* omitted - other initialization that takes place */
fetcher = (DirectionsFetcherFragment)
manager.findFragmentByTag(DIRECTIONS_FETCHER_FRAGMENT);
if (fetcher == null)
{
Log.d(TAG, "Creating new DirectionsFetcherFragment instance");
fetcher = DirectionsFetcherFragment.newInstance( /*omitted*/);
transaction = manager.beginTransaction();
transaction.add(fetcher, DIRECTIONS_FETCHER_FRAGMENT);
transaction.commit();
}
}
and here are some samples from the fragment code
class DirectionsFetcherFragment extends Fragment
{
/* string constants omitted */
public static DirectionsFetcherFragment newInstance(/*omitted*/)
{
DirectionsFetcherFragment instance = new DirectionsFetcherFragment();
Bundle data = new Bundle();
/* omitted - adding the necessary data to the bundle */
instance.setArguments(data);
return instance;
}
public DirectionsFetcherFragment()
{
super();
/* omitted - setting default values for member variables */
}
#Override
public void onCreate(Bundle savedInstance)
{
Log.wtf(TAG, "onCreate()");
super.onCreate(savedInstance);
setRetainInstance(true);
Bundle arguments = getArguments();
/* omitted - other initializations tasks that take place */
}
}
Here's what's happening. On the initial activity creation the fetcher reference is null as expected and thus I create a new fragment and add it via a transaction. When/if I rotate the device though, when the activity's onCreate() method runs the fetcher reference is null, no fragment is returned by findFragmentByTag(). In the LogCat I can clearly see that the fragment's onDetach() -> onAttach() methods are run for the first fragment, but for some reason the fragment is then garbage collected and a new fragment is created.
Here is the LogCat output:
D/DirectionsViewer﹕ Initializing from intent <<-- Initial activity creation
D/DirectionsViewer﹕ Creating new DirectionsFetcherFragment instance <<-- Fragment creation
A/DirectionsFetcherFragment﹕ onAttach()
A/DirectionsFetcherFragment﹕ onCreate()
V/DirectionsViewer﹕ onStart()
V/DirectionsViewer﹕ onResume()
V/DirectionsViewer﹕ onSaveInstanceState() <<-- Rotationing and saving instance
A/DirectionsFetcherFragment﹕ onDetach() <<-- Fragment correctly detaches
D/DirectionsViewer﹕ Restoring from saved instance <<-- Activity restoration
D/DirectionsViewer﹕ Creating new DirectionsFetcherFragment instance <<-- Why is this happenning, shouldn't I get a reference to the existing fragment?
A/DirectionsFetcherFragment﹕ onAttach()
A/DirectionsFetcherFragment﹕ onCreate()
V/DirectionsViewer﹕ onStart()
V/DirectionsViewer﹕ onResume()
V/DirectionsViewer﹕ Deleting DirectionsViewer instance <<-- This is the old activity that gets garbage collected
A/DirectionsFetcherFragment﹕ Deleting DirectionsFetcherFragment instance <<-- This is the old fragment instance that gets garbage collected
Am I missing something? Thanks in advance for any answers.

Categories

Resources