Search code examples
androidandroid-fragmentscallbackandroid-dialogfragment

Why is DialogFragment causing ClassCastExcepetion?


I have a ViewPager fragment instantiating a DialogFragment. Because the Android Developer guide says...

"All Fragment-to-Fragment communication is done through the associated Activity. Two Fragments should never communicate directly."

... this DialogFragment provides a callback to MainActivity, which then feeds that information down to the ViewPager fragment.

My DialogFragment "ModeDialogFragment" calls the following method from within onClick:

((MainActivity)getActivity()).updateData();

The updateData method in MainActivity identifies the ViewPager fragment 'MyFragment' and starts a method doUpdateData().

public void updateData(){
        // Call function that generates the correct tab to identify MyFragment
        MyFragment myFrag = (MyFragment) findFragmentByPosition(3); // Exception occurs here
        myFrag.doUpdateData();
        }

public Fragment findFragmentByPosition(int position) {
        int viewId = R.id.pager
        return getSupportFragmentManager().findFragmentByTag(
                makeFragmentName(viewId, position));
    }

String makeFragmentName(int viewId, int position)
    {
         return "android:switcher:" + viewId + ":" + position;
    }

However, when I run the code, I get the following ClassCastException:

07-13 01:19:53.972: E/AndroidRuntime(1660): java.lang.ClassCastException: com.example.myapp.ModeDialogFragment cannot be cast to com.example.myapp.MyFragment

(I can provide the rest if asked.) I understand they can't be cast as the same if they are quite different, but why is ModeDialogFragment interfering at all? findFragmentByPosition() is not returning a ModeDialogFragment, I don't see why MainActivity should complain. The only connection is that ModeDialogFragment is performing the call. I am rather new to this, so is it possible that I am I doing my callback incorrectly?

EDIT: Some extra code. This is my ViewPagerAdapter:

public class TabsPagerAdapter extends FragmentPagerAdapter {

    public TabsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int index) {
        switch (index) {
        case 0:
            // Fragment0 tab
            return new Fragment0();
        case 1:
            // Fragment1 tab
            return new Fragment1();
        case 2:
            // Fragment2 tab
            return new Fragment2();
        case 3:
            // MyFragment tab
            return new MyFragment();
        }

        return null;
    }

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

}

This is how I am starting my ModeDialogFragment, extending Fragment, from clicking a ListView item:

    myList.setOnItemClickListener(new AdapterView.OnItemClickListener()
    {
        public void onItemClick(AdapterView<?> parentAdapter, View view, int position, long id)
        {
            FragmentManager fm = getFragmentManager();
            FragmentTransaction ft = fm.beginTransaction();

            ModeDialogFragment modeDialog = ModeDialogFragment.newInstance(R.string.mode_calibration);
            String title = makeFragmentName(R.id.pager, 3); // As in MainActivity. Takes ViewPager ID and fragment number.
            //ft.add(modeDialog, title);
            modeDialog.show(ft, title);
        }
    }

Solution

  • From the code you posted it seems you are using the same tag for both the fragments that are involved. ModeDialogFragment is added using makeFragmentName(R.id.pager, 3) which is the same tag that the ViewPager uses for MyFragment, so when the FragmentManager tries to retrieve the fragment using the tag you get the wrong one.

    The solution is to change the tag that you use when showing the ModeDialogFragment.