TheGreat004 TheGreat004 - 1 month ago 16
Android Question

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" />

Answer

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.