androidandroid-viewpagerandroid-listfragment

ListFragments Wrong Data Weird Pager


I hope someone can assist please. I have a Fragment hosting multiple list fragments using support library. The list fragments are supposed to display data that i retrieve form an async task in the parent fragment. I have been trying to figure out exactly how the data is being loaded because it is not loading correctly.

Each time the list display fragment is launched it preforms an async task to get and parse Json into an ArrayList <ArrayList <HashMap <String, String> > >

Each List fragment queries the parent fragment for data at its position in the ArrayList. eg. For the 3rd page in it should retrieve arrList[2] which contains an `ArrayList <HashMap <String, String> > to display as a list.

The pager is acting weird. Maybe i am not understanding the lifecycle of the fragments or how the pager uses them. I have 7 Fragments. If i start on frag3 the pager will show fragment 3 with no data on it. It also loads fragment 2 and 4 with no data. If i go left to frag 1 it will display fragment 1 correctly and load fragment 0. I can properly switch to frag 0 but if i switch to frag 2 it loads data from frag 0 and loads frag 0's data into all of the rest of the views. If i go back and forth enough it will replace all data in every fragment with data from frag 0. I believe that it does not load data immediately because it does not have the data when the viewpager launches. I have not made it wait for the async task yet.

I thought that each fragment gets its view redrawn each time it is taken far enough from view. So i put Update in the onCreateView() of the fragment. I feel like this is a small thing that i have just misplaced or i am overlooking it. I tried to implement FragmentStatePagerAdapter but i do not think that i did it right.

Any Help is much Appreciated And i am very open to discussion if i am just doing things horribly wrong. I usually do. It never fails. Create something to find out i need to rewrite everything.

public class ListFragmentDisplay extends SherlockFragment {
public static final String TAG = "listFragmentDisplay";

Calendar calendar = Calendar.getInstance();
private int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
// listbyday is a list of hash maps each list of hash maps represents a day
// of the week with items for that Object
private ArrayList<ArrayList<HashMap<String, String>>> listByDay = null;
private String objectName = null;
private ViewPager pager;
private FragAdapter adapter;

public ArrayList<HashMap<String, String>> getList(int day) {
    return listByDay.get(day);

}
private void getObjectName() {
    barName = ((MainFragActivity) getActivity()).getobjectSelected();
}
public static ListFragmentDisplay newInstance() {
    return new ListFragmentDisplay();
}
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // Inflate the ListView layout file.
    initArrList();
    getObjectName();
    fillList();
    return inflater.inflate(R.layout.list_view, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    pager = (ViewPager) view.findViewById(R.id.viewPager);
    adapter =new FragAdapter(getChildFragmentManager());
    if (pager.getAdapter() == null)
        pager.setAdapter(adapter);
    reload();
    pager.setOnPageChangeListener(new OnPageChangeListener() {
        @Override
        public void onPageScrollStateChanged(int arg0) {}

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {reload();}
        
        @Override
        public void onPageSelected(int arg0) {  
        }
    });
    pager.setCurrentItem(dayOfWeek-1);
}
private void initArrList() {
    if (listByDay == null) {
        listByDay = new ArrayList<ArrayList<HashMap<String, String>>>();
    } else {
        listByDay.clear();
    }
    for (int i = 0; i < 7; i++) {
        ArrayList<HashMap<String, String>> hm = new ArrayList<HashMap<String, String>>();
        listByDay.add(hm);
    }
}
synchronized private void fillList() {
    LoadWebTask lWT = new LoadWebTask();
    executeAsyncTask(lWT, getSherlockActivity().getApplicationContext());
}

FragmentPager

public class FragAdapter extends FragmentPagerAdapter {
private static final String[] CONTENT = new String[] { "frag0", "frag1",
        "frag2", "frag3", "frag4", "frag5", "frag6" };
public FragAdapter(FragmentManager fm) {
    super(fm);

}
@Override
public Fragment getItem(int arg0) {
    return MyListFragment.newInstance(arg0);
}
@Override
public int getCount() {
    return CONTENT.length;
}
@Override
public CharSequence getPageTitle(int position) {
    return CONTENT[position % CONTENT.length];
}
}

ListFragment

public class MyListFragment extends SherlockListFragment {
public static final String NAME_TAG = "name";
public static final String DESCRIPTION_TAG = "description";
private static int dow;
public static final String TAG = "listFragment";
// Keys used in Hashmap that will be mapped to the rows
String[] dFrom = { NAME_TAG, DESCRIPTION_TAG };
private ArrayList<HashMap<String, String>> list;
int[] dTo = { R.id.name, R.id.description };
    public void upDateList() {
    //**************************Not really sure if this is how things are supposed 
            //** to be done. For my small data- set i feel like it will work but i would 
            //** be interested in knowing how else this might be done. 
              ListFragmentDisplay lFD = (ListFragmentDisplay) this
            .getParentFragment();
        dList = lFD.getList(dow);
}
public static MyListFragment newInstance(int pos) {
    MyListFragment frag = new MyListFragment();
    dow = pos;
    return (frag);
}
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    upDateList();
    View results = inflater.inflate(R.layout.list_fragment, container,
            false);
    SimpleAdapter adapter = new SimpleAdapter(getParentFragment()
            .getActivity(), list, R.layout.listrow, dFrom, dTo);
    setListAdapter(adapter);
    return results;
}
}

Edit. Solved Code: In List Fragment The Initial Question has been solved. I am only in the process of implementing the onPostExecute callback to the ListFragmentDisplay. Much Thanks to Luksprog for solving my very noobish mistake. I made dow static without knowing its affect. I think it was actually something that Eclipse offered to solve a conflict. I should have read it closer.

 public class MyListFragment extends SherlockListFragment {
public static final String NAME_TAG = "name";
public static final String DESCRIPTION_TAG = "description";

public static final String TAG = "listFragment";
// Keys used in Hashmap that will be mapped to the rows
String[] dFrom = { NAME_TAG, DESCRIPTION_TAG };
private ArrayList<HashMap<String, String>> list;
int[] dTo = { R.id.name, R.id.description };

    SimpleAdapter adapter = null; **NEW**
    
    public void upDateList() {
                      ListFragmentDisplay lFD = (ListFragmentDisplay) this
            .getParentFragment();
        dList = lFD.getList(getArguments().getInt(TAG)); **NEW**
            if(adapter != null)  **NEW**
            adapter.notifyDataSetChanged(); **NEW**
}
public static MyListFragment newInstance(int pos) {
    MyListFragment frag = new MyListFragment();

    Bundle args = new Bundle(); **NEW**
    args.putInt(TAG, pos); **NEW**
    frag.setArguments(args); **NEW**

    return (frag);
}
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    upDateList();
    View results = inflater.inflate(R.layout.list_fragment, container,
            false);
    adapter = new SimpleAdapter(getParentFragment()
            .getActivity(), list, R.layout.listrow, dFrom, dTo);
    setListAdapter(adapter);
    return results;
}
}

Solution

  • Is there any reason why you made the dow variable from MyListFragment as static? With the static keyword your fragments from the ViewPager will share their position so you'll call the lFD.getList(dow); method with the wrong position most of the cases. Make dow a private instance field: private int dow;

    About the rest of the code, it looks ok, see if the change above solves the problem. To update your data in the inner fragments you could follow this scenario: