2

In my FragmentActivity I have a fragment. This fragment loads data from server. I want we user clicks on refresh button then I call a method in fragment and do refreshing process.

I created an interface in FragmentActivity and set its variable when user clicks on refresh button. The code is like this:

public class MainScreen extends FragmentActivity {
    public interface OnRefreshSelected {
        public void refreshFragment(boolean flag);
    }

    private OnRefreshSelected onRefreshSelected;

    @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            Log.i(TAG, "Try to create MainScreen...");

            setContentView(R.layout.activity_main);

        onRefreshSelected = (OnRefreshSelected) MainScreen.this;
    }

     @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.activity_main, menu);
            return true;
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
                    case R.id.menu_refresh:
                        onRefreshSelected.refreshFragment(true);
                        return true;
                    default:
                        return super.onOptionsItemSelected(item);
        }
    }
}

And in Fragment class i implemented this interface:

public class CategoryFragment extends Fragment implements OnRefreshSelected {
    @Override
    public void refreshFragment(boolean flag) {
        Log.i(TAG, "refresh requested. Try to reload data for this fragment...");

        getData();
    }
} 

When I run, the application crashes and logcat shows this message:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.astro.recipe.activities/com.astro.recipe.activities.MainScreen}: java.lang.ClassCastException: com.astro.recipe.activities.MainScreen

and points to this line:

onRefreshSelected = (OnRefreshSelected) MainScreen.this;

What is the best way to have access to a method of fragment from its host? any suggestion would be appreciated. Thanks

Hesam
  • 52,260
  • 74
  • 224
  • 365

2 Answers2

4

Executing this

onRefreshSelected = (OnRefreshSelected) MainScreen.this;

you are assigning your activity in onRefreshSelected field, trying to cast it to your interface, but your activity doesn't implement the interface, that's why ClassCastException raised.

Instead use something like this

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
                case R.id.menu_refresh:
                    CategoryFragment fragment = (CategoryFragment) getFragmentManager()
                        .findFragmentById(R.id.category_fragment);
                    if (fragment != null) {
                        fragment.getData();
                    }
                    return true;
                default:
                    return super.onOptionsItemSelected(item);
    }

Your activity can call methods in the fragment by acquiring a reference to the Fragment from FragmentManager, using findFragmentById() or findFragmentByTag().

biegleux
  • 13,179
  • 11
  • 45
  • 52
  • Thanks, but I prefer using Interfaces. Therefore, I replaced onRefreshSelected = (OnRefreshSelected) MainScreen.this; by onRefreshSelected = new TopRecipesFragment(); and onRefreshSelected = new CategoryFragment(); Now it works fine. Thanks again. – Hesam Jul 24 '12 at 04:52
  • Please see my related question: http://stackoverflow.com/questions/24833912/refresh-fragment-ui-from-fragmentactivity – Dr.jacky Jul 19 '14 at 07:45
-1

I agree with biegleux... But my suggestion is

public class CategoryFragment extends Fragment{

   private static CategoryFragment categoryFrag;

    private CategoryFragment(){}

    public static CategoryFragment getInstance(){
        if(null == categoryFrag){
            categoryFrag = new CategoryFragment();
        }

        return categoryFrag;
    }

    public void  getData(){
       /*** Screen Refresh code****/
    }
} 

I your active when he selects option

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
                case R.id.menu_refresh:
                    CategoryFragment fragment = CategoryFragment.getInstance();
                     fragment.getData();

                    return true;
                default:
                    return super.onOptionsItemSelected(item);
    }
Pradeep
  • 2,530
  • 26
  • 37