notifyDataSetChanged не обновляет представление переработчика

У меня есть ArrayList, получающий данные от IntentService. После того, как я получил свои данные, я обновил свой адаптер и позвонил notifyDataSetChanged(). Но это не меняет данные.

Вот мой код:

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"));
    }
}

}

И вот мой код адаптера:

 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;
    }
}

}

Когда я извлекаю данные из ArrayList и печатаю в журнале, я получаю обновленные значения. Но эти обновления не отражаются в моем списке переработчиков.

Я видел другие вопросы в Stack Overflow, в которых говорилось, что:

  1. нам нужно обновить данные из того же объекта Fragment

  2. notifyDataSetChanged()` следует вызывать из потока пользовательского интерфейса.

Я не понимаю, чего мне не хватает.


person Sindhu    schedule 21.02.2017    source источник
comment
добавьте код адаптера   -  person ATEF    schedule 21.02.2017
comment
вы не отправляете новые данные на адаптер!   -  person ATEF    schedule 21.02.2017
comment
@Atef Hares Я вызвал addAll() для ArrayList, а затем вызвал notifyDataSetChanged() для адаптера. Этих двух строк недостаточно для обновления RecyclerView?   -  person Sindhu    schedule 21.02.2017
comment
Да, я думаю, что нет, вы должны убедиться, что данные внутри адаптера обновлены, я имею в виду, что вы должны убедиться, что mStationPojoList из вашего адаптера обновлено, прежде чем вызывать notifyDataSetChanged() , если вы не знаете, как его обновить, Я могу помочь!   -  person ATEF    schedule 21.02.2017
comment
@AtefHares Пожалуйста, дайте мне знать. Я попытался вызвать mRecyclerView.setAdapter(mAdapter) перед вызовом notifyDataSetChanged(). Данные обновляются, но RecyclerView снова прокручивается вверх.   -  person Sindhu    schedule 21.02.2017
comment
Проверьте мой ответ   -  person ATEF    schedule 21.02.2017
comment
Взгляните на этот пример, в пакете ui есть адаптер для представления ресайклера. Адаптер настраивается во FlagListFragment. github.com/AlexGoja/flag-application. Таким образом, идея состоит в том, чтобы иметь сеттер для данных внутри вашего адаптера и вызывать этот сеттер, как только ваши данные будут готовы (т.е., возможно, из API отдыха и т. д.).   -  person Alex Goja    schedule 21.02.2017
comment
Я думаю, что вам следует переосмыслить, как должен работать ваш код. В onBindViewHolder вы сортируете массив при вызове этого метода, что увеличивает вероятность задержки прокрутки.   -  person Iulian Popescu    schedule 21.02.2017
comment
отлаживайте свой код, добавляя фиктивные данные и проверяя, работает ли каждая строка, потому что отладка - единственное решение для этого кода!   -  person Hamza Zaidi    schedule 21.02.2017
comment
НЕ не нужно переустанавливать stationArrivalPOJO в адаптере, ссылка на stationArrivalPOJO уже передана в конструктор адаптера, и любое действие на stationArrivalPOJO повлияет на адаптер, например clear(), addAll()..., если вы этого не сделаете. повторите создание экземпляра stationArrivalPOJO, например stationArrivalPOJO = new Array..., у вас все хорошо, и ваш код правильный, у вас проблема где-то еще. в качестве доказательства, отладки или добавления журналов в onBindViewHolder() для печати используемых данных вы увидите, что они обновлены.   -  person Yazan    schedule 21.02.2017


Ответы (1)


вам не нужно снова устанавливать адаптер для обновления элементов.

Вместо этого, как вы пытались сделать, вы должны вызвать notifyDataSetChanged(), но для этого вам нужно сначала обновить данные adpater, вот хороший способ сделать это:

1-

добавьте этот метод в свой адаптер

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

2-

в вашем Nearby_ViewPager_Stations внутри addAdapter сделайте следующее:

  stationArrivalPOJO.addAll(resultData);
  mAdapter.updateData(stationArrivalPOJO); // updating adapter's data
  mAdapter.notifyDataSetChanged(); //notifying the adapter
person ATEF    schedule 21.02.2017
comment
Я пробовал, как вы сказали. Но все равно не обновляет данные - person Sindhu; 21.02.2017
comment
Невозможно!, уверены ли вы, что передали правильные новые данные, я имею в виду, что перед вызовом mAdapter.updateData(stationArrivalPOJO); вы уверены, что stationArrivalPOJO имеет новые данные или нет? вы отладили код? - person ATEF; 21.02.2017
comment
Я добавил следующие строки: stationArrivalPOJO.clear(); stationArrivalPOJO.addAll (данные результата); Представление Adapter_recyclerView = новый Adapter_recyclerView(); view.updateData(stationArrivalPOJO); mAdapter.notifyDataSetChanged(); - person Sindhu; 21.02.2017
comment
Я прочитал ваш код! Пожалуйста, отладьте код и убедитесь, что resultData содержит новые данные и, следовательно, stationArrivalPOJO содержит новые данные - person ATEF; 21.02.2017
comment
Да. resultData получает новые данные. И я напечатал данные в updateData() в классе адаптера. Я также получил новые данные в классе адаптера - person Sindhu; 21.02.2017
comment
Я понятия не имею, в чем может быть проблема! Я думаю, что-то не так с адаптером, но это способ отправки обновленных данных в адаптер, и они были отправлены, как вы говорите. - person ATEF; 21.02.2017
comment
Почему вы не используете getItemId() в адаптере? - person ATEF; 21.02.2017
comment
Окончательно !!!! Проблема не в адаптере. На самом деле я динамически добавляю макет в onBindViewHolder(). Этот макет не обновляется новыми значениями. Большое спасибо за помощь в отслеживании моей проблемы. - person Sindhu; 21.02.2017
comment
@Sindhu onBindViewHolder является частью вашего адаптера, проблема всегда в адаптере: D, пожалуйста :), пожалуйста, примите ответ, чтобы другие люди узнали решение проблемы вопроса. - person ATEF; 21.02.2017
comment
Отредактируйте свой ответ, указав, что проблема связана с моим адаптером bindViewHolder(). Тогда я соглашусь :) - person Sindhu; 21.02.2017
comment
@Sindhu, я действительно не понимаю, что вы сделали, вам лучше отредактировать его и предоставить решение, которое вы сделали (внизу моего ответа), и вы, я приму ваше редактирование! - person ATEF; 21.02.2017