Reputation: 21
I have
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
after turning my device (changing configuration) and clicking on item in RecyclerView. Clicking on RecyclerView item have to start a new fragment.
Here is on item click method in MainActivity:
public class MainActivity extends AppCompatActivity implements
MyFragment.OnFragmentInteractionListener,
ListAdapter.OnRecyclerViewItemClickListener{
// ... some code ...
@Override
public void OnItemClickListener(int position) {
MyFragment myFragment = MyFragment.newInstance(position);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.activity_main_layout, myFragment,
myFragment.TAG);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}
I have the error in
fragmentTransaction.commit();
Here is item clicking code in adapter:
public class ListAdapter extends
RecyclerView.Adapter<ListAdapter.ViewHolder> implements Serializable {
private OnRecyclerViewItemClickListener mListener;
/*... some code here ... */
// constructor
ListAdapter(Context context, ArrayList<ListItem> notesArrayList) {
mListener = (OnRecyclerViewItemClickListener) context;
}
public interface OnRecyclerViewItemClickListener {
void OnItemClickListener(int position);
}
class ViewHolder extends RecyclerView.ViewHolder implements
View.OnClickListener {
ConstraintLayout layout;
TextView title;
ViewHolder(View itemView) {
super(itemView);
title = itemView.findViewById(R.id.note_title);
itemView.setOnClickListener(this);
}
@Override
public void onClick(View view) {
int position = getAdapterPosition();
mListener.OnItemClickListener(position);
}
}
}
And I also use onSaveInstantState and onRestoreInstanceState in MainActivity to keep RecyclerView data. Thanks.
P.S.
I found a solution here:
commitAllowingStateLoss()
but it doesn't work for me, with it, nothing happens after clicking...
P.P.S.
Full stacktrace:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.dojo.stackoverflowproblem, PID: 17220
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:2044)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:2067)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:680)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:634)
at com.dojo.stackoverflowproblem.notepad.MainActivity.OnItemClickListener(MainActivity.java:118)
at com.dojo.stackoverflowproblem.notepad.ListAdapter$ViewHolder.onClick(ListAdapter.java:98)
at android.view.View.performClick(View.java:6294)
at android.view.View$PerformClick.run(View.java:24770)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Upvotes: 2
Views: 722
Reputation: 509
I met a similar issue. Trace deep into the codes of .commit() or .show(), and you can find it go through checkStateLoss() of FragmentManager.java. There also be a function isStateSaved(). So, you can see this is a simple way to fix the problem:
if(!getSupportFragmentManager().isStateSaved()) { //this to avoid IllegalStateException
//This makes it safe to do your fragment.commit(); or fragmentDialog.show() etc. here.
}
in FragmentManager.java:
checkStateLoss() checks mStateSaved to throw the exception. So, !isStateSaved() is just the condition not to throw the exception.
private void checkStateLoss() {
if (mStateSaved) {
throw new IllegalStateException(
"Can not perform this action after onSaveInstanceState");
}
if (mNoTransactionsBecause != null) {
throw new IllegalStateException(
"Can not perform this action inside of " + mNoTransactionsBecause);
}
}
@Override
public boolean isStateSaved() {
return mStateSaved;
}
Upvotes: 1