Passing a listener to a custom Fragment in Android

I suppose you want to re-use the Fragment with various different listeners. So your approach is not ideal since you can not use the Bundle for that. A better approach would be to use the callback design pattern e.g.

public class RegWizardFragmentInfo extends Fragment {

    public interface RegWizardCallback {
        void onClick();
    }
}

Your Activity would implement that interface. Since a Fragment only lives inside an Activity you can get the callback instance from it by using the lifecycle method onAttach(). It would look like this

public class RegWizardFragmentInfo extends Fragment {
    private RegWizardCallback callback;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            callback = (RegWizardCallback) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement RegWizardCallback ");
        }
    }

    public interface RegWizardCallback {
        void onClick();
    }
}

With that you can simply call callback.onClick inside the listener of the Button.


You can use a callback in your Fragment:

public class RegWizardFragmentInfo extends Fragment {

    private Button button;

    private OnClickCallback callback;

    public interface OnClickCallback {
        void onClick();
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        callback = (OnClickCallback) context;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                callback.onClick();
            }
        });
    }
}

and implement this new interface in your parent Activity


The other answers assign the listener in onAttach. While this will work, it requires that the calling Activity (and not, say, an anonymous class) implement your interface. Moreover, it forces you to cast the Context given to you in onAttach to an instance of your interface, which can cause crashes and is generally considered bad form. You might instead create a method to set the listener inside your Fragment:

public class RegWizardFragmentInfo extends Fragment {

    private OnClickListener mListener;

    public interface OnClickListener {
        void onClick();
    }

    /**
     * Call at any time after this fragment has been constructed.
     */
    public void setListener(OnClickListener listener) {
        mListener = listener;
    }

    /* ...other stuff... */
}

I can think of three disadvantages to this approach:

  1. You need to call an extra method every time you want to instantiate the Fragment.
  2. You can't guarantee that mListener is set at any time. You may need to pepper your Fragment code with null checks.
  3. You need to be careful to make sure the listener remains set after lifecycle events such as screen rotation.