Cannot refresh/update listview in a fragment from another fragment in ViewPager

Jani Bela picture Jani Bela · Apr 22, 2013 · Viewed 9.8k times · Source

I am having a hard time figuring out the next thing.

What I have: I have a viewpager and several pages in it. In this question only two of them is important, lets call them Fragment1 and Fragment2 and they are next to each other. Fragment1 contains a listview which is filled with data from the internet (external database). Fragment2 contains a simple button.

My goal: If I click on the button in Fragment2, I add a new item to the external database. I would like to update/refresh the listview in the Fragment1 with this new item.

The notifyDataChanged() doesnt work in my case, however so far I was convinced that it reinstantiates every pages.. I am going to introduce my problem the clearest way I can, so lets see the code I have, this is my ViewPager adapter:

class MyPagerAdapter extends FragmentStatePagerAdapter {
        public List<String> fragmentsA; 

        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
            fragmentsA = fragments;
        }

        @Override
        public Fragment getItem(int position) {
           return Fragment.instantiate(context, fragmentsA.get(position));

        }

        @Override
        public CharSequence getPageTitle(int position) {
           return mEntries.get(position % CONTENT.length).toUpperCase();
        }

        @Override
        public int getCount() {
          return mEntries.size();
        }

        @Override
        public int getItemPosition(Object object) {
            return POSITION_NONE;
        }
    }

Fragment1 onCreateView() (shortly):

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

    getData();
    View view = inflater.inflate(R.layout.latestapps_tab, container, false);
    lw = (ListView) view.findViewById(R.id.lw);
    context = getActivity().getApplicationContext();
    act = this.getActivity();
    m_adapter = new ItemAdapter();
    lw.setAdapter(m_adapter);

return view;
}

I create the ViewPager and the adapter, I set the adapter for the ViewPager afterwards I fill the my viewpager with my fragments in my Main class. After this I am goint to have a fully functional ViewPager with 2 fragments.

  pager = (ViewPager)findViewById( R.id.viewpager );
  adapter = new MyPagerAdapter(getSupportFragmentManager());
  indicator = (TabPageIndicator)findViewById( R.id.indicator );
  pager.setAdapter( adapter );
  indicator.setViewPager( pager );
  pager.setCurrentItem(INITIAL_PAGE);
  pager.setOffscreenPageLimit(3);

  //adding fragments to the pager
  fragments.add( Fragment1.class.getName());    
  fragments.add( Fragment2.class.getName()); 

In the Fragment1 I have a listview with some textviews in every list item. The loading works perfectly: I create the ArrayLists and I fill thoes lists with data from the external database. After loading is done, I fill the listviews with these tons of data. In Fragment 2 I click on the button and I would like that listview to be updated so a new row should be created in the listview with some data from the external database. (of course writing into the database works)

My guess, that I might not refresh the ArrayLists or I dont reinstantiate the Fragment1, so the getDataFromSQL() method never turns only if I exit and launch the application again or I swipe so much in the ViewPager that the Fragment1 gets detached. So I cannot update or refresh the Fragment1. Could someone help in this questionL?

EDIT

I managed to make it happen with delivering a message to the fragment2 to update itself. But I am not sure if it is a good solution and there is not a better way, i.e. just refreshing somehow the whole fragment.

SOLUTION

Okay I think it must have been my laziness but I solved it now. For everyone who still wants to refresh a fragment from another one or just make conection between fragments, I tell you the appropriate approach:

  1. You have to implement your own listener which helps you communicate between the fragments through the holder activity. This can be found here: http://developer.android.com/training/basics/fragments/communicating.html . Very simple and useful.

  2. You have to retrieve the fragment, which is again simple: Retrieve a Fragment from a ViewPager These Q offers several acceptable way, I used the SpareArray solution.

Thank you for the help anyway!

Answer

Eluvatar picture Eluvatar · Apr 27, 2013

you need be able to get your fragments from your activity, to do that you need to get the fragment from your adapter, you will need to add a couple methods to your page adapter

public Fragment getFragment(ViewPager container, int position, FragmentManager fm) {
    String name = makeFragmentName(container.getId(), position);
    return fm.findFragmentByTag(name);
}

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

then from your activity make the following method

public Fragment getFragmentbyPosition(int position) {
    return adapter.getFragment(pager, position, getSupportFragmentManager());
}

now on fragment2 call the following:

Fragment1 fragment1 = (Fragment1) ((MyActivity)getActivity()).getFragmentbyPosition(0);

now you will be able to call public methods on fragment1 from fragment 2, so just use that in your onClick and tell fragment1 to update it's listview.

now the reason makeFragmentName works is that is how the FragmentPagerAdapter creates the tag for the fragments it makes.