Search code examples
androidandroid-fragmentsandroid-dialogfragmentandroid-loadermanager

How to restart Fragment's LoaderManager from hosting Activity?


I have a main activity with a ViewPager with two tabs. Each tab contains a fragment.

One of those fragment contains a RecyclerView and FAB that shows a DialogFragment when clicked that allows the user to add a new item to the RecyclerView. This fragment also implements the LoaderCallbacks interface (the RecyclerView data is backed by Cursors):

public class MyListFragment extends Fragment
        implements LoaderManager.LoaderCallbacks<Cursor> {

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_list, container, false);

        FloatingActionButton fab = (FloatingActionButton) view.findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                DialogFragment dialog = SaveDialogFragment.newInstance();
                dialog.show(getFragmentManager(), "SaveDialogFragment");
            }
        });

        mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
        ...
        getLoaderManager().initLoader(0, null, this);
        return view;
    }

    ...
}

Inside of this DialogFragment class I declare a interface for the callbacks of the Positive and Negative buttons:

public class SaveDialogFragment extends DialogFragment {
    ...
    public interface SaveDialogListener {
        void onSaveDialogPositiveClick(String str1, String str2);
    }
    ...
}

Since I use the SaveDialogFragment.onAttach() method to obtain a reference to the hosting of this Dialog I need to implement the SaveDialogListener in the MainActivity (not in the fragment):

public class MainActivity extends AppCompatActivity implements SaveDialogFragment.SaveDialogListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        mViewPager = (ViewPager) findViewById(R.id.viewPager);
        setupViewPager(mViewPager);
        TabLayout tabs = (TabLayout) findViewById(R.id.tabs);
        tabs.setupWithViewPager(mViewPager);
    }

    @Override
    public void onSaveDialogPositiveClick(String name, String number) {
        ...
        saveItem(new ItemRow(name, number));
        // HERE I MUST RESET THE LOADER, BUT HOW???
        // getLoaderManager().restartLoader(0, null, ???);
    }
}

So in summary: I launch a DialogFragment from a Fragment and this DialogFragment notifies to the hosting Activity when the user adds a new item.

My doubt comes from the fact that I am using a LoaderManager inside of the Fragment (because the Fragment is responsable to initialize the Loader and reset it). But when the onSaveDialogPositiveClick is invoked how can the Activity restart the Loader of the Fragment? How is the most correct way to handle this scenary?

Since the Adapter of the ViewPager holds the reference to the Fragments it seems wrong to keep a reference to the fragment in the activity just for only restart the LoaderManager:

getLoaderManager().restartLoader(0, null, showListFragment);

Thanks in advance.


Solution

  • I would do it like this, Created an callback interface SaveDialogListener with the method . Implement it in the Calling Fragment (MyListFragment).During the DialogFragment creation set your calling fragment MyListFragment as target fragment. Use this method dialogFrag.setTargetFragment(MyListFragment.this, 0). Now you can use this interface to send data to your fragment.

    In your DialogFragment class,

    SaveDialogListener callback = 
               (SaveDialogListener) getTargetFragment();
    callback. onSaveDialogPositiveClick(param1,param2);
    

    Note: Use getChildFragmentManager() to show DialogFragment.

    So that you will get the callback inside your fragment. And can reload the loadermanager there.