Android: BaseAdapter перерисовывает те же данные - PullRequest
0 голосов
/ 24 октября 2019

Я создал пользовательский адаптер, расширив BaseAdapter, и пытаюсь отобразить прокручиваемое представление списка, которое расширяется всякий раз, когда пользователь прокручивает весь путь до самого дна. Однако при обновлении базового ArrayList вместо создания новых представлений для новых элементов и добавления их в конец представления списка некоторые уже существующие элементы в ArrayList перерисовываются.

Я загружаю данные JSONиз блога Wordpress и хотите отобразить изображение и выдержку из каждого сообщения в виде списка. Я реализовал прослушиватель в виде списка, который вызывается всякий раз, когда пользователь прокручивает страницу вниз. При прокрутке до конца выполняется загрузка следующих трех самых последних сообщений в блоге. Когда загрузка закончится, я обновляю ArrayList BlogPosts blogPosts, как показано ниже, и вызываю notifyDataSetChanged(). Я проверил, что данные JSON загружены правильно: первые три последних сообщения отображаются, когда я переключаюсь в режим просмотра архива (см. Видео). По завершении загрузки вызывается addToPosts(). Параметр posts также является правильным и состоит из следующих трех сообщений.

list_view.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/archive_page"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

<ProgressBar
    android:id="@+id/loading_panel_archive"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:indeterminate="true"
    android:layout_gravity="center"/>

<ListView
    android:id="@+id/list_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>
</FrameLayout>

list_view_item.xml

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/test"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
    android:id="@+id/image_view_lv"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="top"
    />

<TextView
    android:id="@+id/text_view_lv"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    android:textColor="@color/colorPrimary"/>
</LinearLayout>

CustomAdapter.java

public class CustomAdapter extends BaseAdapter {
    private Context context;
    private ArrayList<BlogPost> blogPosts;

    public CustomAdapter(Context context, ArrayList<BlogPost> blogPosts) {
        this.blogPosts = blogPosts;
        this.context = context;
    }

    @Override
    public int getViewTypeCount() {
        return getCount();
    }

    @Override
    public int getCount() {
        return blogPosts.size();
    }

    @Override
    public Object getItem(int i) {
        return blogPosts.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(final int i, View view, ViewGroup viewGroup) {
        final ViewHolder holder;

        if (view == null) {
            holder = new ViewHolder();
            LayoutInflater inflater = (LayoutInflater) context
               .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.list_view_item, 
                viewGroup,  false);
            holder.tvname = view.findViewById(R.id.text_view_lv);
            holder.iv = view.findViewById(R.id.image_view_lv);

            final BlogPost currentPost = (BlogPost) getItem(i);
            holder.tvname.setText(currentPost.getContent());

            if (!currentPost.isAsyncTaskFinished()){
                currentPost.setListener(new BlogPost.ChangeListener() {
                    @Override
                    public void onChange() {
                        holder.iv.setImageBitmap(currentPost.getBitmap());
                    }
                });
            }else{
                holder.iv.setImageBitmap(currentPost.getBitmap());
            }

        }
        return view;
    }


public void addToPosts(ArrayList<BlogPost> posts){
    this.blogPosts.addAll(posts);
    this.notifyDataSetChanged();
}

private class ViewHolder {
    protected TextView tvname;
    private ImageView iv;
    }
}

Настройка представления списка и настраиваемого адаптера:

ListView lv = findViewById(R.id.list_view);
CustomAdapter adapter = new CustomAdapter(getApplicationContext(),
firstThreePosts);
lv.setAdapter(adapter);

ProgressBar bar = findViewById(R.id.loading_panel_archive);
bar.setVisibility(View.GONE);

//scroll listener...

Я ожидал, что следующие три сообщения будут добавлены в представление списка, однако эточто случилось: https://1drv.ms/v/s!AuPD10kPw_c5ghHaajc4OYFvkV1K?e=iVc2mS

Шестой и пятый посты перерисовываются снова и снова, а новые посты никогда не вырисовываются. Может быть, параметр i в getView вызывает такое поведение, но я не могу понять, что происходит. Любая помощь будет высоко ценится!

1 Ответ

0 голосов
/ 26 октября 2019

Попробуйте это getView ():

@Override
public View getView(int i, View view, ViewGroup viewGroup) {
    final ViewHolder holder;

    if (view == null) {
        holder = new ViewHolder();
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.list_view_item, viewGroup,  false);
        holder.tvname = view.findViewById(R.id.text_view_lv);
        holder.iv = view.findViewById(R.id.image_view_lv);
        view.setTag(holder);
    } else {
        holder = (ViewHolder)view.getTag();
    }

    final BlogPost currentPost = (BlogPost) getItem(i);
    holder.tvname.setText(currentPost.getContent());

    if (!currentPost.isAsyncTaskFinished()){
        currentPost.setListener(new BlogPost.ChangeListener() {
            @Override
            public void onChange() {
                holder.iv.setImageBitmap(currentPost.getBitmap());
            }
        });
    }else{
        holder.iv.setImageBitmap(currentPost.getBitmap());
    }

    return view;
}

Надеюсь, это поможет!

...