Search code examples
androidmultithreadingandroid-dialogfragment

Access a database from a DialogFragment and toast a message


I have a DialogFragment which displays a simple yes/no question. When the user presses "yes", I perform a database request (which basicaly deletes an entry). I then toast a message to report a success or failure to the user.

I try to avoid calling the database from the UI thread, so I created a thread which will delete the entry, and from that thread I call a handler in the DialogFragment to display the toast message.

My problem is that when the user presses the button, the thread is started and the dialog is closed. As the thread is started, the data is deleted from the database. But when I toast my message from the handler, the DialogFragment is already detached from the parent Activity so I don't have a context anymore to call Toast.makeText().

My question is how can I toast the message ?

I know I could create a Service to handle the database operation, but wouldn't it be too much hassle ? Is there a simpler way ?

Thanks !

EDIT : here is my code, to help you understand my problem :

public class EraseHistoryDialogFragment extends DialogFragment {
    private HistoryDatabaseHandler mHistoryDbHandler;

    private final static int MSG_NOTIFY_EMPTYDB = 1;
    private final static int MSG_NOTIFY_DELENTRY = 2;
    private final static int MSG_NOTIFY_NODELETION = 3;
    private Context mContext;


    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MSG_NOTIFY_DELENTRY:
                Toast.makeText(mContext,
                        getS    tring(R.string.historytab_erased_entry),
                        Toast.LENGTH_SHORT).show();
                break;
            case MSG_NOTIFY_EMPTYDB:
                Toast.makeText(mContext,
                        getS    tring(R.string.historytab_history_cleared),
                        Toast.LENGTH_SHORT).show();
                break;
            case MSG_NOTIFY_NODELETION:
                Toast.makeText(mContext,
                        getS    tring(R.string.historytab_erase_failed),
                        Toast.LENGTH_SHORT).show();
                break;
            }
        };
    };
    private Runnable mEraseHistoryRunnable = new Runnable() {

        @Override
        public void run() {
            if (mHistoryDbHandler.clearAllTables()) {
                mHandler.sendEmptyMessage(MSG_NOTIFY_EMPTYDB);
            } else {
                mHandler.sendEmptyMessage(MSG_NOTIFY_NODELETION);
            }
        }
    };

    private class EraseEntryRunnable implements Runnable {
        private String mEntryId;

        public EraseEntryRunnable(String entryID) {
            mEntryId = entryID;
        }

        @Override
        public void run() {
            if (mHistoryDbHandler.deleteEntry(mEntryId)) {
                mHandler.sendEmptyMessage(MSG_NOTIFY_DELENTRY);
            } else {
                mHandler.sendEmptyMessage(MSG_NOTIFY_NODELETION);
            }
        }
    };

    public static EraseHistoryDialogFragment newInstance(String message,
            String entryID, boolean eraseAll) {
        EraseHistoryDialogFragment frag = new EraseHistoryDialogFragment();
        Bundle args = new Bundle();
        args.putString("message", message);
        args.putString("entryid", entryID);
        args.putBoolean("eraseall", eraseAll);
        frag.setArguments(args);
        return frag;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        mHistoryDbHandler = HistoryDatabaseHandler.getInstance(getActivity());
        mContext = getActivity().getApplicationContext();
        String message = getArguments().getString("message");
        final String entryID = getArguments().getString("entryid");
        final boolean eraseAll = getArguments().getBoolean("eraseall");
        return new AlertDialog.Builder(getActivity())
                .setMessage(message)
                .setPositiveButton(R.string.groupstab_yes,
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog,
                                    int whichButton) {
                                if (eraseAll) {    
                                    Thread emptyDbT = new Thread(
                                            mEraseHistoryRunnable);
                                    emptyDbT.start();
                                } else {
                                    Thread deleteEntryT = new Thread(
                                            new EraseEntryRunnable(entryID));
                                    deleteEntryT.start();
                                }
                            }
                        })
                .setNegativeButton(R.string.groupstab_no,
                        new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog,
                                    int whichButton) {
                                getDialog().dismiss();
                            }
                        }).create();
    }

}


Solution

  • Try getActivity().getApplicationContext() to get the ApplicationContext