Why is onResume method of a Fragment never fired after dismissing a DialogFragment which was launched from the Fragment?
Asked Answered
P

3

17

I am going to explain my problem as short as possible.

I have a Fragment called FragmentA which displays a DialogFragment after clicking on a specific button.

public class FragmentA extends Fragment implements OnClickListener {

    ...

    @Override
    public void OnClick(View v) {
        if (v == dialogButton) {
            showDialog();
        }
    }

    public void showDialog() {
        String diagName = getResources().getString(R.string.dialog_title);
        MyDialog myDialog = MyDialog.newInstance(getFragmentAValue());
        myDialog.show(getFragmentManager(), diagName);
    }
}

public class MyDialog extends DialogFragment implements OnClickListener {
    ...
    @Override
    public void onClick(View view) {
        if (view == acceptButton) {
            ...
        }
        else if (view == cancelButton) {
            ...
        }
    }
}

The dialog is dispalyed without any problem. But my problem consists in after myDialog is dismissed onResume() method in FragmentA is never called and FragmentA is shown and you can interact with it without any problem.

public class FragmentA extends Fragment implements OnClickListener {

    ...

    @Override
    public void onResume() {
        super.onResume();
        resumeFragmentA();
    }
}

So, what I have done in order to fix this issue is copying an instance of FragmentA in the end of onActivityCreated() method and call the method resumeFragmentA() when user has closed the dialog.

public class FragmentA extends Fragment implements OnClickListener {

    FragmentA fragmentA = null;

    ...

    @Override
    public void onResume() {
        super.onResume();
        resumeFragmentA();
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {

        ...

        fragmentA = this;
    }

    ...
}

public class MyDialog extends DialogFragment implements OnClickListener {
    ...
    @Override
    public void onClick(View view) {
        if (view == acceptButton) {
            storeData();
            dismissDialog();
        }
        else if (view == cancelButton) {
            dismissDialog();
        }
    }

    public void dismissDialog() {
        FragmentA.fragmentA.resumeFragmentA();
        dismiss();
    }

}

I know this solution is tricky but I do not know to solve in a more brilliant way. Do you know it? Any Idea? Thanks in advance!

For a better reading of my code, here you have my full code:

public class FragmentA extends Fragment implements OnClickListener {

    ...

    FragmentA fragmentA = null;

    ...

    @Override
    public void OnClick(View v) {
        if (v == dialogButton) {
            showDialog();
        }
    }

    public void showDialog() {
        String diagName = getResources().getString(R.string.dialog_title);
        MyDialog myDialog = MyDialog.newInstance(getFragmentAValue());
        myDialog.show(getFragmentManager(), diagName);
    }

    @Override
    public void onResume() {
        super.onResume();
        resumeFragmentA();
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {

        ...

        fragmentA = this;
    }

    ...
}


public class MyDialog extends DialogFragment implements OnClickListener {

    ...

    static MyDialog newInstance(int value) {
        MyDialog fragment = new MyDialog ();
        Bundle args = new Bundle();
        args.putInt("value", value);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onClick(View view) {
        if (view == acceptButton) {
            storeData();
            dismissDialog();
        }
        else if (view == cancelButton) {
            dismissDialog();
        }
    }

    public void dismissDialog() {
        FragmentA.fragmentA.resumeFragmentA();
        dismiss();
    }

    ...

}
Praetorian answered 5/10, 2013 at 11:7 Comment(0)
P
4

Now Google has released Android Architecture Components library, the best solution is to use a shared ViewModel between both Fragments with your Activity as the one that implements LifecycleRegistryOwner.

Doing this, we will avoid refreshing UI calling onResume and we don't need to code any tricky solution.

A solution could be the following one:

public MyActivity extends AppCompatActivity {

    ...

}

public class FragmentA extends Fragment implements OnClickListener {

    ...

    private SharedViewModel mSharedViewModel;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mSharedViewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);

        mSharedViewModel.getData().observe(this, value -> {
            updateUIValue(value);
        });

    }

    @Override
    public void OnClick(View v) {
        if (v == dialogButton) {
            showDialog();
        }
    }

    @Override
    public void OnClick(View v) {
        if (v == dialogButton) {
            showDialog();
        }
    }

    public void showDialog() {
        String diagName = getResources().getString(R.string.dialog_title);
        MyDialog myDialog = MyDialog.newInstance(getFragmentAValue());
        myDialog.show(getFragmentManager(), diagName);
    }
}

public class MyDialog extends DialogFragment implements OnClickListener {

    ...

    private SharedViewModel mSharedViewModel;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mSharedViewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);

        mSharedViewModel.getData().observe(this, value -> {
            updateUIValue(value);
        });

    }

    @Override
    public void onClick(View view) {
        if (view == acceptButton) {
            ...

            mSharedViewModel.setValue(newValue);
        }
        else if (view == cancelButton) {
            dismiss();
        }
    }
}


public class SharedViewModel extends ViewModel {

    final MutableLiveData<Resource<Value>> data = new MutableLiveData<>();

    public MutableLiveData<Value> getData() {
        return data;
    }

    public void setValue(Value newValue) {
        this.data.setValue(newValue)
    }
}
Praetorian answered 16/9, 2017 at 15:52 Comment(0)
P
4

If you just want to call onResume of FragmentA, make a call to startActivityForResult inside your DialogFragment, and start your FragmentActivity. This will call onResume.

public void dismissDialog() {
   getActivity().startActivityForResult(getActivity().getIntent(), 10);
   dismiss()
}
Phototherapy answered 2/12, 2013 at 13:38 Comment(3)
I don't know if it's the best way, but it worked for me. Can you explain why? It forces the onResume of the activity (and onResumed of the contained fragment) to be called?Herschel
This creates a new Activity, which doesn't solve our problem !Lexielexigraphy
@SriKrishna this is just a workaround but can solve the problem in some situation. You can change the launchmode to singleTask or singleTop to avoid 2 instance of the same activityFruiter
P
4

Now Google has released Android Architecture Components library, the best solution is to use a shared ViewModel between both Fragments with your Activity as the one that implements LifecycleRegistryOwner.

Doing this, we will avoid refreshing UI calling onResume and we don't need to code any tricky solution.

A solution could be the following one:

public MyActivity extends AppCompatActivity {

    ...

}

public class FragmentA extends Fragment implements OnClickListener {

    ...

    private SharedViewModel mSharedViewModel;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mSharedViewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);

        mSharedViewModel.getData().observe(this, value -> {
            updateUIValue(value);
        });

    }

    @Override
    public void OnClick(View v) {
        if (v == dialogButton) {
            showDialog();
        }
    }

    @Override
    public void OnClick(View v) {
        if (v == dialogButton) {
            showDialog();
        }
    }

    public void showDialog() {
        String diagName = getResources().getString(R.string.dialog_title);
        MyDialog myDialog = MyDialog.newInstance(getFragmentAValue());
        myDialog.show(getFragmentManager(), diagName);
    }
}

public class MyDialog extends DialogFragment implements OnClickListener {

    ...

    private SharedViewModel mSharedViewModel;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mSharedViewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);

        mSharedViewModel.getData().observe(this, value -> {
            updateUIValue(value);
        });

    }

    @Override
    public void onClick(View view) {
        if (view == acceptButton) {
            ...

            mSharedViewModel.setValue(newValue);
        }
        else if (view == cancelButton) {
            dismiss();
        }
    }
}


public class SharedViewModel extends ViewModel {

    final MutableLiveData<Resource<Value>> data = new MutableLiveData<>();

    public MutableLiveData<Value> getData() {
        return data;
    }

    public void setValue(Value newValue) {
        this.data.setValue(newValue)
    }
}
Praetorian answered 16/9, 2017 at 15:52 Comment(0)
G
0

Another way is by implementing an interface. Create an interface and let the activity/fragment (which one you need) implements it, then pass itself as an interface object to your DialogFragment.

CustomDialogFragment df = new CustomDialogFragment();
Bundle b = new Bundle();
b.putSerializable(KEY, this); // current activity/fragment that implements the interface
df.setArguments(b);
df.show(getFragmentManager(), TAG);

Then in your DialogFragment get the listener, and call the listener's method when you need to (in this case after/before you called dismiss()).

Gooseflesh answered 23/6, 2016 at 6:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.