androidandroid-recyclerviewnotifydatasetchanged

notifyDataSetChanged does not update my recycler view


I have a ArrayList getting data from IntentService. After I got my data I updated my adapter and called notifyDataSetChanged(). But it does not change data.

Here is my code:

public class Nearby_ViewPager_Stations extends Fragment {

private View mRootView = null;
private RecyclerView mRecyclerView;
private RecyclerView.LayoutManager mLayoutManager;
private StationsReceiver mStationsReciever;
private MKLoader mProgressBar;

private RecyclerView.Adapter mAdapter;
private Context mContext;
ArrayList<ArrayList<StationArrivalPOJO>> stationArrivalPOJO = new ArrayList<>();

private static final String TAG = "NearbyViewPagerStations";

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    mContext = context;
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    if (mRootView == null) {
        mRootView = inflater.inflate(R.layout.nearby_viewpager_stations, container, false);
        mRecyclerView = (RecyclerView) mRootView.findViewById(R.id.recycler_view);
        mProgressBar = (MKLoader) mRootView.findViewById(R.id.progressBar);
    }

    mStationsReciever = new StationsReceiver(new Handler());
    mLayoutManager = new LinearLayoutManager(mContext);
    mRecyclerView.setLayoutManager(mLayoutManager);
    mAdapter = new Adapter_recyclerView(stationArrivalPOJO);
    mRecyclerView.setAdapter(mAdapter);

    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            startIntentService();
            handler.postDelayed(this, 20*1000);
        }
    }, 1000);
    return mRootView;
}

private void startIntentService() {
    Intent intent1 = new Intent(mContext, GetAllStationsAndStopsIntentService.class);
    intent1.putExtra("Receiver", mStationsReciever);
    intent1.putExtra("latitude", Constants.latitude);
    intent1.putExtra("longitude", Constants.longitude);
    mContext.startService(intent1);
}

void addAdapter(ArrayList<ArrayList<StationArrivalPOJO>> resultData) {
    mProgressBar.setVisibility(View.GONE);

    if (stationArrivalPOJO.size() > 0)
        stationArrivalPOJO.clear();
    stationArrivalPOJO.addAll(resultData);
    mAdapter.notifyDataSetChanged();

    Log.v(TAG, "added all data: "+ stationArrivalPOJO.get(0).get(0).getTimeToStation());
}

public class StationsReceiver extends ResultReceiver {
    StationsReceiver(Handler handler) {
        super(handler);
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        super.onReceiveResult(resultCode, resultData);

        addAdapter((ArrayList<ArrayList<StationArrivalPOJO>>)resultData.getSerializable("StationPOJO"));
    }
}

}

And here is my Adapter code:

 class Adapter_recyclerView extends RecyclerView.Adapter {

private ArrayList<ArrayList<StationArrivalPOJO>> mStationPojoList;
private LinearLayout mLinearLayout;

private Context mContext;

private static final String TAG = "AdapterRecyclerView";

Adapter_recyclerView(ArrayList<ArrayList<StationArrivalPOJO>> data) {
    mStationPojoList = data;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    ((ViewHolder)holder).stationNameTV.setText(mStationPojoList.get(position).get(0).getStationName());

    ArrayList<String> mUniqueStationName = new ArrayList<>();  //Unique platform names of a station got from hash set 'uniqStatNames'
    HashSet<String> uniqStatNames = new HashSet<>(); //Unique platform names of a station

    for (int i = 0;i<mStationPojoList.get(position).size(); i++) {
        uniqStatNames.add(mStationPojoList.get(position).get(i).getPlatformName()
        + mStationPojoList.get(position).get(i).getTowards());
    }

    for(Iterator<String> it = uniqStatNames.iterator() ; it.hasNext() ; ) {
        mUniqueStationName.add(it.next());
    }

    for (int j=0; j<mUniqueStationName.size(); j++) {
        ArrayList<StationArrivalPOJO> arrivalPOJOs = new ArrayList<>();   //Platform wise categorized train details
        for (int i = 0;i<mStationPojoList.get(position).size(); i++) {
            if (mUniqueStationName.get(j).contains(mStationPojoList.get(position).get(i).getPlatformName())
                    && mUniqueStationName.get(j).contains(mStationPojoList.get(position).get(i).getTowards())) {
                arrivalPOJOs.add(mStationPojoList.get(position).get(i));
            }
        }

        Collections.sort(arrivalPOJOs, new Comparator<StationArrivalPOJO>() {
            @Override
            public int compare(StationArrivalPOJO stationArrivalPOJO, StationArrivalPOJO t1) {
                return stationArrivalPOJO.getTimeToStation() - t1.getTimeToStation();
            }
        });

        for (int k=0; k<arrivalPOJOs.size(); k++) {
        Log.v(TAG, j+":"+mUniqueStationName.size()+"boo"+arrivalPOJOs.toString());
        Log.v(TAG, "boom " + arrivalPOJOs.get(k).getPlatformName() + ":" + arrivalPOJOs.get(k).getTowards());

        RelativeLayout relativeLayout = new RelativeLayout(mContext);
        relativeLayout.setPadding(16, 16, 16, 16);
        LinearLayout linearLayout = new LinearLayout(mContext);
        linearLayout.setOrientation(LinearLayout.VERTICAL);

        TextView trainName = new TextView(mContext);
        trainName.setText(arrivalPOJOs.get(k).getPlatformName());

        TextView towards = new TextView(mContext);
        towards.setText(arrivalPOJOs.get(k).getTowards());

        linearLayout.addView(trainName);
        linearLayout.addView(towards);

        RelativeLayout.LayoutParams layoutParams1 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
        layoutParams1.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        linearLayout.setLayoutParams(layoutParams1);

        TextView time = new TextView(mContext);
        time.setText(String.valueOf(arrivalPOJOs.get(k).getTimeToStation()));

        RelativeLayout.LayoutParams layoutParams2 = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
        layoutParams2.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
        time.setLayoutParams(layoutParams2);

        relativeLayout.addView(linearLayout);
        relativeLayout.addView(time);

        mLinearLayout.addView(relativeLayout);
        }}
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View rootView =  LayoutInflater.from(parent.getContext())
            .inflate(R.layout.adapter_recyclerview,parent,false);
    mContext = parent.getContext();

    mLinearLayout = (LinearLayout) rootView.findViewById(R.id.cardViewLinearLayout);
    TextView mStationName = (TextView) rootView.findViewById(R.id.stationName);

    return new ViewHolder(rootView, mStationName);
}

@Override
public int getItemCount() {
    return mStationPojoList.size();
}

private static class ViewHolder extends RecyclerView.ViewHolder {
    TextView stationNameTV;

    ViewHolder(View view, TextView stationNameTV) {
        super(view);
        this.stationNameTV = stationNameTV;
    }
}

}

When I retrieve data from ArrayList and print in log station I get updated values. But that updates are not getting reflected in my recycler list.

I have seen other questions in Stack Overflow saying that:

  1. we need update data from the same Fragment object

  2. notifyDataSetChanged()` should be called from ui thread.

I dont understand what I am missing.


Solution

  • you don't need to set the adapter again to update elements.

    Instead as you were trying to do, you should call notifyDataSetChanged() but to do that you have to update the adpater's data first, here is a good way to do that:

    1-

    add this method to your adapter

    public void updateData(final ArrayList<ArrayList<StationArrivalPOJO>> stationArrivalPOJO ) {
            mStationPojoList= new ArrayList<>();
            mStationPojoList.addAll(stationArrivalPOJO);
        }
    

    2-

    in your Nearby_ViewPager_Stations inside addAdapter, do the following:

      stationArrivalPOJO.addAll(resultData);
      mAdapter.updateData(stationArrivalPOJO); // updating adapter's data
      mAdapter.notifyDataSetChanged(); //notifying the adapter