ddk
ddk

Reputation: 101

Accessing fragment methods from parent Activity

Okay, this must be so simple and obvious that no one can believe that anyone would ask it. I have researched it for over a day and I can't find an answer. It's possible that my entire understanding of how this should work is flawed, but, here is my issue.

I have 2 fragment tabs ParFragment and HandicapFragment running under an activity called EnterCourseData via a FragmentStatePagerAdapter called TabsPagerAdapter. Both fragments show 2 EditText views that display the same values and both fragments have a save button that grabs these values from the EditText views and saves these values. The button also initiates a callback to notify the EnterCourseData activity that the values may have changed. I want EnterCourseData to force both fragments to update with the new values. My assumption is that since both tabs exist during this time, both are accessible. I am trying to get to one using findFragmentByTag("ParFragment"), but I am getting a null value.

Please, either tell me what I am doing is best handled some other way, or tell me how to fix what I am doing. Here's the code... Here's the TabsPagerAdapter:

public class TabsPagerAdapter extends FragmentStatePagerAdapter {
    int courseNumber, teeNumber;

    public TabsPagerAdapter(FragmentManager fm, int courseNumber, int teeNumber) {
        super(fm);
        this.courseNumber = courseNumber;
        this.teeNumber = teeNumber;
    }

    @Override
    public Fragment getItem(int index) {

        switch (index) {
        case 0:
            // Par Entry activity
            Fragment parFragment = new ParFragment();
            Bundle args = new Bundle();
            args.putInt(ParFragment.ARG_COURSE_NUMBER, courseNumber);
            args.putInt(ParFragment.ARG_TEE_NUMBER, teeNumber);
            parFragment.setArguments(args);
            return parFragment;
        case 1:
            // Handicap Entry fragment activity
            Fragment hcpFragment = new HandicapFragment();
            args = new Bundle();
            args.putInt(HandicapFragment.ARG_COURSE_NUMBER, courseNumber);
            args.putInt(HandicapFragment.ARG_TEE_NUMBER, teeNumber);
            hcpFragment.setArguments(args);
            return hcpFragment;
        }

        return null;
    }

    @Override
    public int getCount() {
        // get item count - equal to number of tabs
        return 2;
    }
}

Here's one of the two (almost) identical fragments:

    public class ParFragment extends Fragment {
    public static final String ARG_COURSE_NUMBER = "courseNumber", ARG_TEE_NUMBER = "teeNumber";
    Tee tee;
    String courseName;
    View rootView;

    OnParSavedListener mCallback;

    // Container Activity must implement this interface
    public interface OnParSavedListener {
        public void onParSaved();
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mCallback = (OnParSavedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnParSavedListener");
        }
    }



    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        rootView = inflater.inflate(R.layout.fragment_par, container, false);

        Button buttonSave = (Button) rootView.findViewById(R.id.savePars);
        buttonSave.setOnClickListener(savePars);

        Bundle args = getArguments();
        Course course = Global.getCourse(args.getInt(ARG_COURSE_NUMBER));
        courseName = course.getName();
        ((TextView) rootView.findViewById(R.id.display_course_name)).setText(course.getName());
        tee = course.getTee(args.getInt(ARG_TEE_NUMBER));
        ((TextView) rootView.findViewById(R.id.display_tee_name)).setText(tee.getTeeName());
        refreshParScreen();


        return rootView;
    }

    View.OnClickListener savePars = new View.OnClickListener() {
        public void onClick(View v) {
            tee.setSlope(Integer.parseInt(((EditText) rootView.findViewById(R.id.enter_tee_slope)).getText().toString()));
            tee.setRating(Double.parseDouble(((EditText) rootView.findViewById(R.id.enter_tee_rating)).getText().toString()));
            GolfTools.addUpdateCourse(rootView.getContext(), Global.getCourse(courseName));
            mCallback.onParSaved();
        }
      };

      public void refreshParScreen(){
          ((TextView) rootView.findViewById(R.id.enter_tee_slope)).setText(Integer.toString(tee.getSlope()));
          ((TextView) rootView.findViewById(R.id.enter_tee_rating)).setText(Double.toString(tee.getRating()));

      }
}

and here's most of the activity:

    public class EnterCourseData extends FragmentActivity implements ActionBar.TabListener, ParFragment.OnParSavedListener{


    private ViewPager viewPager;
    private TabsPagerAdapter mAdapter;
    private ActionBar actionBar;
    // Tab titles
    private String[] tabs = { "Pars", "Handicaps" };
    private int courseNumber, teeNumber;

    public void onParSaved() {
        // The user saved the Par sheet
        // Refresh par and Handicap tabs
        ParFragment parFrag = (ParFragment) getSupportFragmentManager().findFragmentByTag("ParFragment");

        if (parFrag != null) {
            parFrag.refreshParScreen();
        }
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_enter_tees);
        // Initialization
        Intent mIntent = getIntent();
        courseNumber = mIntent.getIntExtra("courseNumber",0);
        teeNumber = mIntent.getIntExtra("teeNumber",0);

        viewPager = (ViewPager) findViewById(R.id.fragment_container);
        actionBar = getActionBar();
        mAdapter = new TabsPagerAdapter(getSupportFragmentManager(), courseNumber, teeNumber);

        viewPager.setAdapter(mAdapter);
        actionBar.setHomeButtonEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);        

        // Adding Tabs
        for (String tab_name : tabs) {
            actionBar.addTab(actionBar.newTab().setText(tab_name)
                    .setTabListener(this));
        }
        /**
         * on swiping the viewPager make respective tab selected
         * */
        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
   .
   .
   .

I get all the way to the Activity after the button is pressed in the fragment and I want to call the fragment method to repopulate the screen. I use ParFragment parFrag = (ParFragment) getSupportFragmentManager().findFragmentByTag("ParFragment"); and I get a null value. I know "ParFragment" exists because that's how we got here. My understanding is 1) get a pointer to the fragment and, 2) call the method using the pointer.

Please, tell me where my thinking is flawed and exactly how to make this happen.

Thank you

Upvotes: 1

Views: 354

Answers (1)

Rafa Viotti
Rafa Viotti

Reputation: 10530

FragmentStatePagerAdapter does not use tags when adding fragments to the Activity. That is why findFragmentByTag is returning null.

You need to use the method instantiateItem to get the fragment. To get fragment #0.

ParFragment parFrag = (ParFragment) mAdapter.instantiateItem(viewPager, 0)

See this answer.

Upvotes: 2

Related Questions