Calling a fragment method inside a custom view

2019-06-06 15:15发布

问题:

So for some background I've tried to call a method I have in my fragment (that's hosting the custom view) within the custom view.

I've tried using an interface and implementing it in the fragment. I've also tried getting an instance of the fragment in the customview and calling the method that way. For whatever reason, I get null pointers both ways.

Way #1

public SurveyView(Context context, AttributeSet attrs) {
    super(context, attrs);
    setOrientation(VERTICAL);
    options = new ArrayList<>();
    //updatePolls is the interface. 
    updatePolls = new MultipleChoicePollFragment();
}
public interface UpdatePolls {
    void update();
}

Then I call the method in an onClickListener:

v.setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            for (int p = 0; p < options.size(); p++) {
                                if (options.get(p) == v) {
                                    setAnswers(p);
                                    updatePolls.update();
                                }
                            }
                        }
                    });

The method update() gets called in my fragment and I try to display a toast, but it returns with a null pointer.

Way #2

Get an instance of the fragment in the customview's constructor and call the method.

public SurveyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOrientation(VERTICAL);
        options = new ArrayList<>();
    myActivity = (AppCompatActivity)context;
                myActivity.getFragmentManager().findFragmentByTag("MULTIPLE_CHOICE_POLL_FRAGMENT");
            myActivity.update();
}

This also returns a null pointer....

my fragment is:

public class MultipleChoicePollFragment extends Fragment implements SurveyView.UpdatePolls

And the method I implement is:

@Override
public void update() {
    Toast.makeText(getActivity(), "Success", Toast.LENGTH_SHORT).show();
}

回答1:

myActivity = (AppCompatActivity)context;
                myActivity.getFragmentManager().findFragmentByTag("MULTIPLE_CHOICE_POLL_FRAGMENT");

This would work, but you need to use getSupportFragmentManager().



回答2:

You can use a listener (your fragment) and add it to your view (setListener). Or you can use an event bus (GreenRobot, Otto etc). The goal is to submit an event, and have someone listening to it by subscribing / unsubscribing.



回答3:

Instead of trying to obtain it when the custom view is constructed, wait until onCreateView() and register the fragment yourself through a public method.

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle saved) {
    View view = inflater.inflate(...);
    SurveyView surveyView = (SurveyView) view.findViewById(...);
    surveyView.setUpdatePolls(this);
    ...
    return view;
}

Then your SurveyView just needs to do some null checks before trying to call the method (to make sure something registered).

if (updatePolls != null) {
    updatePolls.update();
}