Адаптер RecyclerView принимает неправильные значения во время прокрутки

Я прочитал несколько вопросов о stackoverflow, посвященных этой проблеме, но не смог решить свою проблему. Recyclerview показывает веб-просмотры. Моя проблема в том, что адаптер изначально загружает правильные значения (ниже изображения):

правильное поведение

но когда я прокручиваю вниз и снова прокручиваю вверх до первой позиции, в веб-просмотре отображаются неправильные значения (ниже изображения):

правильное поведение

Я думаю, что эта проблема может возникнуть из-за ранее запущенных загрузок в веб-просмотр, но я понятия не имею, как справиться с этим поведением. Вот связанные части моего кода:

/* in my notation, pg is equivalent to page.*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_ebook_list, container, false);
mEbookRecyclerView = (RecyclerView) view.findViewById(R.id.ebook_recycler_view);
mLayoutManager = new LinearLayoutManager(getActivity());
mEbookRecyclerView.setLayoutManager(mLayoutManager);
updateUI();
return view;
}

@Override
public void onResume() {
super.onResume();
updateUI();
}


private void updateUI() {
if (mAdapter == null) {
    EbookLab ebookLab = EbookLab.get(getActivity());
    List<String> pgs = ebookLab.getPgs();
    mAdapter = new EbookAdapter(pgs);
    mEbookRecyclerView.setAdapter(mAdapter);
}
}

   /* ******codes for preparation of menus which I have ignored *******/

private class EbookHolder extends RecyclerView.ViewHolder {
private String mPg;

public EbookHolder(LayoutInflater inflater, ViewGroup container) {
    super(inflater.inflate(R.layout.list_item_ebook, container, false));
    mListWebView = (WebView) itemView.findViewById(R.id.list_web_View);
    mListWebView.getSettings().setLoadWithOverviewMode(true);
}

public void bindEbook(String pg) {
    mPg = pg;
    mListWebView.loadDataWithBaseURL("file:///android_asset/", "Stack Over Flow " + String.valueOf(glbPos), "text/html", "UTF-8", null);

}
}

private class EbookAdapter extends RecyclerView.Adapter<EbookHolder> {
private List<String> mPgs;
public EbookAdapter(List<String> pgs) {
    mPgs = pgs;
}
@Override
public EbookHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
    LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
    return new EbookHolder(layoutInflater, parent);
}


@Override
public void onBindViewHolder(EbookHolder holder, int position) {
    String pg = mPgs.get(position);
    glbPos = position;//A global variable for position
    holder.bindEbook(pg);
}
@Override
public int getItemCount() {
    return mPgs.size();
}
public void setPgs(List<String> pgs) {
    mPgs.clear();
    mPgs.addAll(pgs);
    notifyDataSetChanged();
}
}

Любая помощь приветствуется.

Обновление: в своем коде я определил mListWebView как глобальную переменную. Но это должно быть определено внутри private class EbookHolder extends RecyclerView.ViewHolder. Затем я удалил метод bindEbook(String pg) и напрямую обновил mListWevView внутри public void onBindViewHolder(EbookHolder holder, int position):

holder.mListWebView.loadDataWithBaseURL("file:///android_asset/", "Stack Over Flow " + String.valueOf(glbPos), "text/html", "UTF-8", null);

Мой вопрос >> Занимает ли вызов bindEbook(String pg) больше времени по сравнению с прокруткой recyclerview или это связано с архитектурой Android??


person Mr. Nobody    schedule 24.04.2016    source источник
comment
ваш видхолдер не прав   -  person Mightian    schedule 24.04.2016
comment
@ war_Hero: Не могли бы вы рассказать мне больше деталей?   -  person Mr. Nobody    schedule 24.04.2016
comment
разместите свой адаптер, я объясню, ТАК ЖЕ, КАК ЖИСТ, ВИДЫ ВНУТРИ ВИДЕОХОЛДЕРА ИСПОЛЬЗУЮТСЯ ДЛЯ ПОДДЕРЖАНИЯ ПОЗИЦИИ   -  person Mightian    schedule 24.04.2016
comment
Требуется больше памяти, так как элементы не перерабатываются   -  person Mightian    schedule 26.04.2016


Ответы (2)


Пожалуйста, попробуйте следующее:

1) поставьте log после String pg = mPgs.get(position); и посмотрите, какое значение pg следует за этой строкой;

В bindEbook():
2) поставьте log, чтобы увидеть, какое значение pg поступает;
3) поставьте mListWebView.clearHistory() или mListWebView.loadUrl("about:blank") перед mListWebView.loadDataWithBaseURL(), просто чтобы увидеть, ваш webview действительно загружает новую страницу

Также - попробуйте заменить webview на простое textView - вы увидите, проблема в webview или в adapter.

person Goltsev Eugene    schedule 24.04.2016
comment
Спасибо за полезный ответ. Я нахожу решение. Я удалил bindEbook(String pg) и напрямую обновил веб-просмотр в методе onBindViewHolder. (1) и (2) являются ключевыми моментами для решения проблемы. (3) не повлияло. Проблема в адаптере. Еще раз спасибо. - person Mr. Nobody; 24.04.2016

У меня была очень похожая проблема, которую я решил после обширной отладки. Я надеюсь это тебе поможет:

В моем проекте я показываю горизонтальный RecyclerView внутри вертикального RecyclerView. Код можно увидеть здесь и здесь, и я объяснил, что я делаю на своем веб-сайте здесь.

Я заметил, что при прокрутке внешнего (вертикального) RecyclerView значения внутреннего (горизонтального) RecyclerView перепутались. Это похоже на вашу проблему. Задайте некоторые консольные команды журнала (Log.v) здесь и там в моем внутреннем адаптере RecyclerView (называемом MeasurementsAdapter), одну конкретно в классе держателя внутреннего представления, где данные связаны: открытый класс MeasurementsViewHolder extends RecyclerView.ViewHolder { [код здесь опущен ]

public MeasurementsViewHolder (View itemView) {
    super(itemView);
    [code omitted here]
}

public void bindMeasurement (String name, double value, String unit, int color) {
    mNameView.setText(name);
    mValueView.setText(String.valueOf(Math.round(value)));
    mUnitsView.setText(unit);
    mBoxLayout.setBackgroundColor(color);
    // Log.v(TAG, name + " " + value); <-- here I was logging
}

Я заметил, что когда я прокручивал в какой-то момент, этот метод «bindMeasurement» больше не выполнялся.

Я предполагаю, что RecyclerView «перерабатывал» некоторые случайные данные. Это не то, что я хотел, и мой результат был очень похож на ваш.

Итак, после того, как я прочитал метод notifyDataSetChanged в документации RecyclerView. В адаптере моего внешнего RecyclerView (называемого Stationsadapter) я изменил метод привязки во внутреннем классе ViewHolder и выполнил там метод adapter.notifyDataHasChanged (см. строку 84 в 1)

   public class StationsViewHolder extends RecyclerView.ViewHolder
       implements View.OnClickListener {public TextView mStationInfoView;
   private MeasurementsAdapter mMeasurementsAdapter;

   /**
    * Constructor of inner class StationsViewHolder
    * @param itemView
    */
   public StationsViewHolder(View itemView) {
       super(itemView);
       [code omitted here]

   }

   /**
    * Bind weather station to view
    * @param station is a class containing data of one weather station
    */
   public void bindStation (Station station) {
       [code omitted here]
       mMeasurementsAdapter.notifyDataSetChanged();
   }

Теперь мои RecyclerViews показывают правильные данные. Я очень надеюсь, что это поможет вам и другим.

Привет Бен

person bedawi    schedule 15.02.2017