Shane
Shane

Reputation: 2375

Elegant way to handle LoaderCallbacks with DialogFragment

I have a DialogFragment which uses a Cursor for setMultiChoiceItems. This Cursor is gotten with the help of the LoaderManager.

What is the best way to handle this with the onCreateDialog method? The loader gets started after this method has been called, so the Cursor isn't available to the AlertDialog.Builder at the start.

Is there a method to update the Dialog UI once onLoadFinished is called? Ideally I'd like to set an initial loading UI, and once the Cursor becomes available then update the UI.

I have an implementation that is working that simply takes the Cursor loading out of the Fragment and into the Activity. I don't like this though since it isn't very modular. I could write up a Fragment class that populated it's own views and swapped them when the Cursor is finished, but this doesn't seem very elegant either.

Since this is more of a design question than a specific coding problem, I've left out sample code. Answers I'm looking for should be based on how to manage this kind of workflow nicely within the DialogFragment class, using the AlertDialog.Builder to create the Dialog view.

Upvotes: 4

Views: 845

Answers (1)

Emanuel Moecklin
Emanuel Moecklin

Reputation: 28856

Old question but maybe the answer helps someone.

  • start the CursorLoader in onCreate(), onCreateView or onActivityCreated(), doesn't really matter imo
  • Create the Adapter and the Dialog in onCreateDialog. The dialog will use an empty adapter till the data is loaded
  • Swap the adapter's cursor in onLoadFinished

Here's some sample code:

public class MyDialogFragment extends DialogFragment implements LoaderManager.LoaderCallbacks<Cursor> {

    private CursorAdapter mAdapter;

    public static MyDialogFragment newInstance() {
        return new MyDialogFragment();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getLoaderManager().initLoader(0, null, this);
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        mAdapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_list_item_single_choice, null,
                    new String[] {FolderColumns.NAME}, new int[] {android.R.id.text1}, 0);

        return new AlertDialog.Builder(getContext())
                .setAdapter(mAdapter, null)
                .create();
    }

    @Override
    public synchronized Loader<Cursor> onCreateLoader(int id, Bundle args) {
        Uri uri = ...;
        return new CursorLoader(getActivity(), uri, null, null, null, null);
    }

    @Override
    public synchronized void onLoaderReset(Loader<Cursor> loader) {
        mAdapter.swapCursor(null);
    }

    @Override
    public synchronized void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        if (cursor != null && !cursor.isClosed()) {
            mAdapter.swapCursor(cursor);
        }
    }

}

Note that the adapter can't be created in onCreate because the onCreateDialog is called before onCreate.

Upvotes: 2

Related Questions