Я использую android.support.v7.widget.RecyclerView для отображения простых элементов, содержащих текст, а в некоторых случаях и изображения. В основном я следовал руководству отсюда https://developer.android.com/training/material/lists-cards.html и просто изменил тип mDataset со String[] на JSONArray и xml ViewHolder. Мой RecyclerView находится в простом фрагменте:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<!-- A RecyclerView with some commonly used attributes -->
<android.support.v7.widget.RecyclerView
android:id="@+id/my_hopps_recycler_view"
android:scrollbars="vertical"
android:layout_centerInParent="true"
android:layout_width="200dp"
android:layout_height="wrap_content"/>
</RelativeLayout>
В этом фрагменте я загружаю всю информацию с веб-сервера. После получения информации я инициализирую элементы в RecyclerView. Я использую LinearLayoutManager, который установлен в методе onCreate моего фрагмента. После добавления адаптера я вызываю метод setHasFixedSize(true) в моем RecyclerView. Мой класс адаптера выглядит так:
import android.graphics.BitmapFactory;
import android.support.v7.widget.RecyclerView;
import android.util.Base64;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.apache.commons.lang3.StringEscapeUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import saruul.julian.MyFragment;
import saruul.julian.R;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
/**
* Fragment holding the RecyclerView.
*/
private MyFragment myFragment;
/**
* The data to display.
*/
private JSONArray mDataset;
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView text;
ImageView image;
public ViewHolder(View v) {
super(v);
text = (TextView) v.findViewById(R.id.my_view_text);
image = (ImageView) v.findViewById(R.id.my_view_image);
}
}
public MyAdapter(MyFragment callingFragment, JSONArray myDataset) {
myFragment = callingFragment;
mDataset = myDataset;
}
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_view, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
try {
JSONObject object = mDataset.getJSONObject(position);
if ( object.has("image") ){
if ( !hopp.getString("image").equals("") ){
try {
byte[] decodedString = Base64.decode(StringEscapeUtils.unescapeJson(object.getString("image")), Base64.DEFAULT);
holder.image.setImageBitmap(BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length));
holder.image.setVisibility(View.VISIBLE);
} catch ( Exception e ){
e.printStackTrace();
}
}
}
if ( object.has("text") ){
holder.text.setText(object.getString("text"));
}
} catch ( Exception e ){
e.printStackTrace();
}
}
// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
return mDataset.length();
}
}
И мой xml для представления внутри моего RecyclerView:
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:padding="@dimen/activity_horizontal_margin">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:id="@+id/my_hopp_people_reached"/>
<ImageView
android:id="@+id/my_hopp_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:adjustViewBounds="true"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:id="@+id/my_hopp_text"/>
<ImageButton
android:id="@+id/my_hopp_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:src="@drawable/ic_action_discard"
/>
</LinearLayout>
</android.support.v7.widget.CardView>
Итак, вот моя проблема: все работает нормально. Текст и изображение отображаются правильно в моем RecyclerView. Однако, если я дойду до конца списка, прокручивая вниз и снова прокручивая вверх, изображения отображаются в элементах, которые не должны содержать изображений. На данный момент у меня девять предметов. Последние два из них содержат картинку. Поэтому я прокручиваю вниз и вижу только текст в первых семи элементах. Достижение конца списка показывает мне две картинки, как и ожидалось. Но если я снова прокрутлю вверх, эти изображения появятся в других элементах.
Прокрутка вверх и вниз изменяет изображения всегда в одном и том же порядке:
- Первая прокрутка вверх (после одиночного спуска) создает картинку во втором элементе.
- Прокрутка вниз создает картинку в 7-м пункте.
- Прокрутка вверх создает изображение в первом элементе.
- Прокрутка вниз ничего не дает.
- Прокрутка вверх создает изображение в третьем элементе, а изображение во втором элементе было перезаписано другим изображением.
- Прокрутка вниз создает изображение в 6-м элементе и позволяет исчезнуть изображению в 7-м элементе.
- И так далее ...
Я уже обнаружил, что метод onBindViewHolder(ViewHolderholder, int position) вызывается каждый раз, когда элемент снова появляется на экране. Я проверил позицию и предоставленную информацию в своем mDataset. Здесь все работает нормально: позиция правильная и предоставленная информация тоже. Текст во всех пунктах не меняется и всегда отображается корректно. У кого-нибудь есть такая проблема и знает какое-то решение?