Search code examples
androidlistviewandroid-listfragmentnotifydatasetchanged

ListFragment is not updated with notifydatasetChanged


I am stuck with listfragment as the fragment listview is not updated with new item addition in allData arrayalist. The data come from server which is passed to listfragment class with the help of interface and result arrives in passData ArrayList<SparseArray<String>> allData. I had checked the size, it is alright in passData() method but the listfragemtn is still not updated. I had tried the every approach to work make the listfragment work with notifyDataSetChanged() and notifydatasetinvalidated() but it didn't work.

Fragment:

public class ViewFeedback extends ListFragment implements PassDataToFeedback
{
    ArrayList<SparseArray<String>> allData;
    CustomAdapter customAdapter;

    @Override
    public void onAttach(Activity activity) {
        // TODO Auto-generated method stub
        super.onAttach(activity);
        Context context=activity;
        ((Activity_ViewFeedback)context).setListener(this);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
    /*  db = new DatabaseManager(getActivity());
        lists = db.getAllLists();
        pAdapter = new PayListAdapter(getActivity(), lists);
        setListAdapter(pAdapter);

        registerForContextMenu(getListView());*/
        allData=new ArrayList<SparseArray<String>>();
        customAdapter=new CustomAdapter(allData);
        setListAdapter(customAdapter);
        setListShown(true);
        setListShownNoAnimation(true);

    }

Adapter:

    public class CustomAdapter extends BaseAdapter
    {
        ArrayList<SparseArray<String>> allData;

        public CustomAdapter(final ArrayList<SparseArray<String>> allData) 
        {
            // TODO Auto-generated constructor stub
            if(allData!=null && allData.size()>0)
                this.allData=allData;
            else
                this.allData=new ArrayList<SparseArray<String>>();
        }

        @Override
        public int getCount() {
            // TODO Auto-generated method stub
            return allData.size();
        }

        @Override
        public Object getItem(int arg0) {
            // TODO Auto-generated method stub
            return arg0;
        }

        @Override
        public long getItemId(int arg0) {
            // TODO Auto-generated method stub
            return arg0;
        }

        @Override
        public View getView(int arg0, View arg1, ViewGroup arg2) {
            // TODO Auto-generated method stub
            ViewHolder viewHolder=null;
            if(arg1==null)
            {
                arg1=LayoutInflater.from(arg2.getContext()).inflate(R.layout.row_layout_view_feedback, arg2, false);
                viewHolder=new ViewHolder(arg1);
                arg1.setTag(viewHolder);
            }else
                viewHolder=(ViewHolder)arg1.getTag();

            viewHolder.tv_msg.setText(allData.get(arg0).get(0));
            viewHolder.tv_from.setText(allData.get(arg0).get(1));
            viewHolder.tv_from.setSelected(true);
            viewHolder.tv_when.setText(allData.get(arg0).get(2));
            viewHolder.tv_when.setSelected(true);
            return arg1;
        }

        public class ViewHolder
        {
            TextView tv_msg;
            TextView tv_from;
            TextView tv_when;

            public ViewHolder(final View view)
            {
                tv_msg=(TextView)view.findViewById(R.id.avf_tv_email);
                tv_from=(TextView)view.findViewById(R.id.avf_tv_from);
                tv_when=(TextView)view.findViewById(R.id.avf_tv_when);
            }
        }
    }

    @Override
    public void passData(ArrayList<SparseArray<String>> allData) {
        // TODO Auto-generated method stub
        if(allData!=null)
        {
            if(this.allData.size()>0)
            {
                this.allData.clear();
                customAdapter.notifyDataSetInvalidated();
            }
            this.allData.addAll(allData);
            customAdapter.notifyDataSetChanged();
        }
    }
}

Fragment Layout:

<fragment
                android:id="@+id/myfragment"
                android:name="android.support.v4.app.ListFragment"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_below="@id/avf_layout_linear"
                class="com.fragments.ViewFeedback" />

Solution

  • The problem is that you are setting your data source to a new reference inside the Adapter by calling this.allData=new ArrayList<SparseArray<String>>();

    Once you initialize the allData list, and set it as the data source for the Adapter, you must never change the reference to a new list.

    There is no need to do a null check, since you initialize it before you pass it in to the Adapter, and you should set the allData data source even if it's an empty list, which it will be at the time of creation.

    It is guaranteed to not be null since you initialize it here before feeding to the CustomAdapter constructor:

     allData=new ArrayList<SparseArray<String>>();
     customAdapter=new CustomAdapter(allData);
    

    Also, it's perfectly valid to start with an empty list as the data source for an Adapter (It just won't show any rows at that point). Once you add data to allData and call notifyDataSetChanged(), the list will be populated at that point.

        public CustomAdapter(final ArrayList<SparseArray<String>> allData) 
        {
            // TODO Auto-generated constructor stub
            //if(allData!=null && allData.size()>0) //no need for this
    
                this.allData=allData;
    
            //This was your problem, remove this code:
            //else
                //this.allData=new ArrayList<SparseArray<String>>();
        }
    

    Then, you can modify allData as needed, and call notifyDataSetChanged() to update the ListView.