user1401232
user1401232

Reputation: 61

Can not perform this action after onSaveInstanceState when Dialog fragment is dismissed

I am stuck with an issue with DialogFragments. I have an Activity which has a button which onclick shows a progress spinner(DialogFragment with a custom View) and then goes to another activity. In my second Activity I have button2 which onclick would send back a Result to my previous activity which should dismiss the progress spinner.

public class MainActivity extends AppCompatActivity {

private Button button;
private int stackLevel;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    stackLevel=0;

    button = (Button)findViewById(R.id.button);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            showProgressDialog();

            Intent intent = new Intent(MainActivity.this,           SecondActivity.class);
            startActivityForResult(intent,2);
        }
    });


}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if(requestCode==2){

        dismissProgressDialog();

    }

}

public void showProgressDialog() {
    stackLevel++;

    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    Fragment prev = getSupportFragmentManager().findFragmentByTag("progressDialog");
    if (prev != null) {
        ft.remove(prev);
    }
    //ft.addToBackStack(null);
    // Create and show the dialog.
    DialogFragment newFragment = LoaderFragment.newInstance(stackLevel);
    //newFragment.show(ft,"progressDialog");
    ft.add(newFragment, "progressDialog");
    ft.commitAllowingStateLoss();
}


public void dismissProgressDialog() {

    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    DialogFragment prev = (DialogFragment) getSupportFragmentManager().findFragmentByTag("progressDialog");
    if (prev != null) {
        prev.dismiss();
    }
        ft.commitAllowingStateLoss();
}


 }

Activity 2

public class SecondActivity extends AppCompatActivity {

private Button button;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.second_layout);

    button = (Button)findViewById(R.id.button2);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            try {
                setResult(2);
            }catch (Exception e){

                e.printStackTrace();
            }


            finish();

        }
    });

}
}

But I am getting following error when I dismiss the dialog fragment

    Caused by: java.lang.IllegalStateException: Can not perform this action     after onSaveInstanceState
 at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1527)
 at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1545)
 at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:654)
 at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:621)
 at android.support.v4.app.DialogFragment.dismissInternal(DialogFragment.java:201)
 at android.support.v4.app.DialogFragment.dismiss(DialogFragment.java:167)
 at com.example.am46517.samplefragmentapplication.MainActivity.dismissProgressDialog(MainActivity.java:70)
 at com.example.am46517.samplefragmentapplication.MainActivity.onActivityResult(MainActivity.java:42)
 at android.app.Activity.dispatchActivityResult(Activity.java:6926)
 at android.app.ActivityThread.deliverResults(ActivityThread.java:4293)
 at android.app.ActivityThread.handleSendResult(ActivityThread.java:4347) 
 at android.app.ActivityThread.-wrap20(ActivityThread.java)

 

Upvotes: 4

Views: 6041

Answers (2)

KnowIT
KnowIT

Reputation: 2502

This is a case where DialogFragment is being dismissed in background, therefore it shall be allowed to dismiss only if it is done with dismissAllowingStateLoss() method. But to use this method you need to show this dialog by using supportFragmentManager only, like this: (pardon me, answer is in Kotlin)

gameLoadingDialog = GameLoadingDialog()
gameLoadingDialog?.show(supportFragmentManager, "gameLoadingDialog") 

Then to dismiss this even in background you can use:

val prev = supportFragmentManager.findFragmentByTag("gameLoadingDialog")
if (prev != null && prev is GameLoadingDialog) {
    prev.dismissAllowingStateLoss()
}

Upvotes: 6

Nelis
Nelis

Reputation: 36

I think there's a problem on the line below; "Cannot resolve symbol LoaderFragment".

DialogFragment newFragment = LoaderFragment.newInstance(stackLevel);

But the reason you may be having a problem with your code could be with how you instantiated the ProgressDialog. Because once you navigate away from MainActivity you've lost the declared locally.

I encountered a similar problem before but later figured a way around it, thus:

  1. Create a parent activity class...
    public class CustomActivity extends AppCompatActivity
  2. Let MainAcvity.java and SecondActivity.java extend CustomActivity.java
  3. Move both dialog methods showProgressDialog() and dismissProgressDialog() into CustomActivity.java, then call them in either MainActivity.java or SecondActivity.java (since both methods would have become shared public methods to any class inheriting CustomActivity)

In the end your files should look something like these..

1. CustomActivity.java

public class CustomActivity extends AppCompatActivity {
private int stackLevel;
public void showProgressDialog ()
{
    stackLevel++;

    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    Fragment prev = getSupportFragmentManager().findFragmentByTag("progressDialog");
    if (prev != null) {
        ft.remove(prev);
    }
    //ft.addToBackStack(null);
    // Create and show the dialog.
    DialogFragment newFragment = LoaderFragment.newInstance(stackLevel);
    //newFragment.show(ft,"progressDialog");
    ft.add(newFragment, "progressDialog");
    ft.commitAllowingStateLoss();
}


public void dismissProgressDialog ()
{

    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    DialogFragment prev = (DialogFragment) getSupportFragmentManager().findFragmentByTag("progressDialog");
    if (prev != null) {
        prev.dismiss();
    }
    ft.commitAllowingStateLoss();
}}

2. MainActivity.java

public class MainActivity extends CustomActivity {
@Override
protected void onCreate (Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Button button = (Button) findViewById(R.id.button);
    button.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick (View view)
        {
            showProgressDialog();

            Intent intent = new Intent(MainActivity.this, SecondActivity.class);
            startActivityForResult(intent, 2);
        }
    });
}

@Override
protected void onActivityResult (int requestCode, int resultCode, Intent data)
{
    if (requestCode == 2) {
        dismissProgressDialog();
    }
}}

3. SecondActivity.java

public class SecondActivity extends CustomActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.second_layout);

    Button button = (Button) findViewById(R.id.button2);
    button.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View view) {

            try {
                setResult(2);
            }
            catch (Exception e) {
                e.printStackTrace();
            }

            finish();
        }
    });
}}

Try this let's see if it works (I pray it does ;-))

Upvotes: 0

Related Questions