Dojo
Dojo

Reputation: 21

Can not perform this action after onSaveInstanceState on RecyclerView item click

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

Answers (1)

Fisher
Fisher

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

Related Questions