I actually just created a similar sort of dialog fragment to what you're asking about. I was for a fairly large app and it was getting kind of ridiculous the amount of dialog listeners our main activity was extending just to listen for the results of a single dialog.
In order to make something a bit more flexible I turned to using ListenableFuture from Google's Guava concurrent library.
I created the following abstract class to use:
public abstract class ListenableDialogFragment<T> extends DialogFragment implements ListenableFuture<T> {
private SettableFuture<T> _settableFuture;
public ListenableDialogFragment() {
_settableFuture = SettableFuture.create();
}
@Override
public void addListener(Runnable runnable, Executor executor) {
_settableFuture.addListener(runnable, executor);
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return _settableFuture.cancel(mayInterruptIfRunning);
}
@Override
public boolean isCancelled() {
return _settableFuture.isCancelled();
}
@Override
public boolean isDone() {
return _settableFuture.isDone();
}
@Override
public T get() throws InterruptedException, ExecutionException {
return _settableFuture.get();
}
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return _settableFuture.get(timeout, unit);
}
public void set(T value) {
_settableFuture.set(value);
}
public void setException(Throwable throwable) {
_settableFuture.setException(throwable);
}
// Resets the Future so that it can be provided to another call back
public void reset() {
_settableFuture = SettableFuture.create();
}
@Override
public void onDismiss(DialogInterface dialog) {
// Cancel the future here in case the user cancels our of the dialog
cancel(true);
super.onDismiss(dialog);
}
Using this class I'm able to create my own custom dialog fragments and use them like this:
ListenableDialogFragment<int> dialog = GetIdDialog.newInstance(provider.getIds());
Futures.addCallback(dialog, new FutureCallback<int>() {
@Override
public void onSuccess(int id) {
processId(id);
}
@Override
public void onFailure(Throwable throwable) {
if (throwable instanceof CancellationException) {
// Task was cancelled
}
processException(throwable);
}
});
This is where GetIdDialog is a custom instance of a ListenableDialogFragment. I can reuse this same dialog instance if needs be by simply calling dialog.reset in the onSuccess and onFailure methods to ensure that the internal Future gets reloaded for adding back to a callback.
I hope this helps you out.
Edit: Sorry forgot to add, in your dialog you can implement an on click listener that does something like this to trigger the future:
private class SingleChoiceListener implements DialogInterface.OnClickListener {
@Override
public void onClick(DialogInterface dialog, int item) {
int id = _ids[item];
// This call will trigger the future to fire
set(id);
dismiss();
}
}