Android fragment state always null in onCreateView method and onActivityCreated method - android

I have used multiple tabs in fragment class. I was failed in saving the state of fragment. I used the method onSaveInstanceState() and save a parameter in it. But when I came back to this fragment the saved state always shows "null". I tried all the questions and answers regarding to this.Still I am facing the same problem. Please could anyone help me to solve this.
MY CODE
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setRetainInstance(true);
super.onCreate(savedInstanceState);
Log.d("savedInstanceStateInfo1", "" + savedInstanceState);
if (null != savedInstanceState) {
nAndroids = savedInstanceState.getInt("nAndroids");
Log.d("NANDROIDS", "" + nAndroids);
}
}
// Log.d("State in oncreate : ",""+savedInstanceState);
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setRetainInstance(true);
Log.d("SavedinstanestateInfo", "" + savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
if (container == null) {
return null;
}
// final ActionBar ab=getActivity().getSupportActionBar();
View v = (LinearLayout) inflater.inflate(R.layout.infotab, container, false);
Log.d("SavedinstanestateInfo", "" + savedInstanceState);
return v;
}
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putInt("nAndroids", nAndroids);
super.onSaveInstanceState(outState);
}

1) Apparently when using setRetainInstance(true), the Bundle for onRestoreInstanceState is null.
https://stackoverflow.com/a/8488107/1011746
2) Not necessary, but more customary to call super.onSaveInstanceState(outState) before making any modifications to outState. Same for super.onRestoreInstanceState(outState) in onRestoreInstanceState(Bundle outState).

Related

TableLayout not showing when restored from savedInstanceState

I have a tableLayout in a fragment that´s not showing anything when the information used to populate the cells is taken from the savedInstanceState bundle from OnCreateVIew()
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = initializeViews(inflater,container);
if (savedInstanceState!= null){
cellsTextArrayList = savedInstanceState.getStringArrayList("extractedTextEt");
for (String word: cellsTextArrayList){
addRow(word);
}
}
return rootView;
}
private void addRow(String word){
final TableRow tr = new TableRow(getActivity().getApplicationContext());
final View view = LayoutInflater.from(getActivity().getApplicationContext()).inflate(R.layout.cell_layout, null);
EditText actualCell = view.findViewById(R.id.cell_text);
actualCell.setText(word);
tr.addView(view);
tableLayout.addView(tr);
}
#Override
public void onSaveInstanceState (Bundle outState)
{
cellsTextArrayList.add("first");
cellsTextArrayList.add("second");
cellsTextArrayList.add("third");
outState.putStringArrayList("extractedTextEt", cellsTextArrayList);
super.onSaveInstanceState(outState);
}
The cellsTextArrayList is being restored from the savedInstanceState object, the addRow() method is the one that´s not working. I ran the code on an Activity and it worked so I think this has to do with the Fragment lifecycle.
using onActivityCreated in fragment.
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
...
if (savedInstanceState != null) {
//Restore the fragment's state here
}
}
and then in the activity, you have to save the fragment's instance in onSaveInstanceState() and restore in onCreate().
class MyActivity extends Activity {
private MyFragment
public void onCreate(Bundle savedInstanceState) {
...
if (savedInstanceState != null) {
//Restore the fragment's instance
mMyFragment = getSupportFragmentManager().getFragment(savedInstanceState, "myFragmentName");
...
}
...
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//Save the fragment's instance
getSupportFragmentManager().putFragment(outState, "myFragmentName", mMyFragment);
}
}

onSaveInstanceState in Fragment not working?

I need help.I don't know what is wron here.Need Saved Instance Data in fragment but it's not working for me? Can anyone help ? Here is my code:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
if (savedInstanceState == null) {
Log.e(getActivity().getClass().getSimpleName(),"DATA is NULL");
}else{
Log.e(getActivity().getClass().getSimpleName(),"DATA IS NOT NULL " + savedInstanceState.getString(Constans.SAMPLEDATA));
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(Constans.MOVIE, movie);
outState.putString(Constans.SAMPLEDATA, "sampleData");
}
This is happening because on screen rotate your activity gets recreated so does the fragment inside it start from initial position again as it was started on activity first launch
You need to add this in onCreate of your activity and set the fragment inside if statement like this example
if (savedInstanceState == null){
launchfragment
} else {
// do nothing
}
hope this helps
Add super.onSaveInstanceState(outState);
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putParcelable(Constans.MOVIE, movie);
outState.putString(Constans.SAMPLEDATA, "sampleData");
super.onSaveInstanceState(outState);
}

What is the best way to save state of RecyclerView?

I have fragment contains recyclerview in main activity
Fragment.java
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = inflater.inflate(R.layout.activity_main, container, false);
initInstances(view);
setRetainInstance(true);
return view;
}
private void initInstances(View view) {
mRecyclerView = (RecyclerView) view.findViewById(R.id.dialogList);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
adapter = new MyAdapter(items);
mRecyclerView.setAdapter(mAdapter);
}
MainActivity.java
in onCreate method:
myFragment = (MyFragment) getSupportFragmentManager().findFragmentByTag(MyFragment.TAG);
if (MyFragment == null) {
MyFragment = new MyFragment();
getSupportFragmentManager().beginTransaction().add(R.id.content_frame,
myFragment, MyFragment.TAG).commit();
}
But when orientation changed, my RecyclerView redrawn.
I've tried save state with overriding onSaveInstanceState and onRestoreInstanceState like this How to prevent custom views from losing state across screen orientation changes or Saving and restoring view state android, but to no avail for me
How to correctly save state of RecyclerView and adapter's items when orientation change?
SOLUTION:
My fragment extends from BaseFragment with some methods:
public class BaseFragment extends Fragment{
Bundle savedState;
public BaseFragment() {
super();
if (getArguments() == null)
setArguments(new Bundle());
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (!restoreStateFromArguments()) {
onFirstTimeLaunched();
}
}
protected void onFirstTimeLaunched() {
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
saveStateToArguments();
}
public void saveStateToArguments() {
if (getView() != null)
savedState = saveState();
if (savedState != null) {
Bundle b = getArguments();
b.putBundle("internalSavedViewState8954201239547", savedState);
}
}
private boolean restoreStateFromArguments() {
Bundle b = getArguments();
savedState = b.getBundle("internalSavedViewState8954201239547");
if (savedState != null) {
onRestoreState(savedState);
return true;
}
return false;
}
private Bundle saveState() {
Bundle state = new Bundle();
onSaveState(state);
return state;
}
protected void onRestoreState(Bundle savedInstanceState) {
}
protected void onSaveState(Bundle outState) {
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onStop() {
super.onStop();
}
#Override
public void onDestroyView() {
super.onDestroyView();
saveStateToArguments();
}
In my fragment I override methods and save state of mLayoutManager
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
protected void onSaveState(Bundle outState) {
super.onSaveState(outState);
outState.putParcelable("myState", mLayoutManager.onSaveInstanceState());
}
#Override
protected void onRestoreState(Bundle savedInstanceState) {
super.onRestoreState(savedInstanceState);
mLayoutManager.onRestoreInstanceState(savedInstanceState.getParcelable("myState"));
}
I searched how to get the scroll position of the RecyclerView, but didn't see where I can retrieve it, so I think the best solution is to handle rotation changes directly in your java code, and preventing your activity to restart on orientation change.
To prevent restarting on orientation change, you can follow this solution.
After preventing your Activity from restart, you can build 2 xml layout files, one for portrait mode, and one for landscape mode, you add a FrameLayout in both xml files, holding the place for your RecyclerView.
When the onConfigurationChange(Configuration newConfig) method is called, you call setContentView(int layoutFile) with the appropriate LayoutFile following the new orientation, and add your RecyclerView you are holding in a member of your class in the FrameLayout.

Passing Arguments to a Fragment via Bundles

Bundle params=new Bundle();
params.putBoolean("isNew", true);
getFragmentManager().beginTransaction()
.replace(R.id.main, Fragment
.instantiate(LandingScreen.this, "com.fragments.FragmentOne",params)).commit()
Now this is Fragment1
public class FragmentOne extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_one, null);
return root;
}
}
Where do i receive the Bundle params, that i sent with when creating this Fragment ?
Kind Regards
You'll receive Bundle in Fragment onCreate(....)
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
boolean isNew=this.getArguments().getBoolean("isNew");
}
You can get the data where Bundle object is accessible as a parameter
onCreate()
onCreateView()
onActivityCreated()
When you use onCreate()
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_layout);
String myData=this.getArguments().getString("myData");
}
When you use onCreateView()
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
String myData=this.getArguments().getString("myData");
return inflater.inflate(R.layout.example_fragment, container, false);
}
When you use onActivityCreated()
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String myData=this.getArguments().getString("myData");
}
Most of the time, you'll use call getArguments() in onCreate(), which gets called sometime after you instantiate the Fragment but before onCreateView() and onActivityCreated() would get called. However, as per Android documentation, if you're calling this from your Activity while it's being created, you're not guaranteed that the Activity has finished initializing before onCreate() is called:
Note that this can be called while the fragment's activity is still in the process of being created. As such, you can not rely on things like the activity's content view hierarchy being initialized at this point. If you want to do work once the activity itself is created, see onActivityCreated(Bundle).
For more information, check out this blog post on Activities and Fragments: http://www.zerotohired.com/2015/02/passing-data-between-activities-and-fragments-in-android.

does Saved instance state on onCreate and onActivityCreated of a fragment differs?

#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.savedInstanceState = savedInstance;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
try {
Log.d("Equals?",savedInstanceState.equals(this.savedInstanceState));
} catch (Exception e) {
Log.d("Equals?",savedInstanceState==this.savedInstanceState);
}
}
Will this always\never or only on some cases log true?
EDIT:
after seeing Henry's comment, lets address my question as if Intent has overriden its equals and it does compare those objects content, not by references...
onCreate(Bundle) called to do initial creation of the fragment.
onActivityCreated(Bundle) tells the fragment that its activity has completed its own Activity.onCreate().
so we can say that Bundle savedInstanceState are same at both places.
for more visit
http://developer.android.com/reference/android/app/Fragment.html
http://developer.android.com/guide/components/fragments.html
you wrote
#Override
public void onCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
this.savedInstanceState = savedInstance;
}
i do not understand which lifecycle mehod is onCreated i think it should be onCreate and the lines should be
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
....}

Categories

Resources