GridView具有无限滚动优化

Pan*_*sky 8 java optimization android gridview infinite-scroll

我已经创建了一个简单的应用程序,从中获取图像,然后GridView以无限滚动显示它们.

我的OnScrollListener:

public class BasicOnScrollListener implements AbsListView.OnScrollListener {

private IOnScroll onScroll;

public BasicOnScrollListener(IOnScroll action) {
    this.onScroll = action;
}

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}

@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    if (firstVisibleItem + visibleItemCount >= totalItemCount - visibleItemCount)
        onScroll.onReachedEnd();
}
}
Run Code Online (Sandbox Code Playgroud)

代码可用于数据处理:

private List<Image> images = new ArrayList<>();

....

private void init() {
    this.imageAdapter = new ImageAdapter(this, images);
    this.gridView.setAdapter(imageAdapter);

    populateGridView();
    this.gridView.setOnScrollListener(new BasicOnScrollListener(() -> {
        populateGridView();
    }));
}

private void  populateGridView() {
    if (!isLoading) {
        isLoading = true;
        this.progressBar.setVisibility(View.VISIBLE);
        imagesRepository.getImages(currentPage, PAGE_SIZE, new IOnRepositoryDataReturn<ImagesList>() {
            @Override
            public void onData(ImagesList data) {
                clearIfNeeded();
                images.addAll(data.images);
                imageAdapter.notifyDataSetChanged();
                onFinish();
            }

            @Override
            public void onError(String error) {
                Toast.makeText(getApplicationContext(), error, Toast.LENGTH_LONG).show();
            }

            private void clearIfNeeded() {
                if (images.size() > 1000) {
                    images.subList(0, 300).clear();
                }
            }

            private void onFinish() {
                progressBar.setVisibility(View.INVISIBLE);
                isLoading = false;
                currentPage = currentPage + 1;
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

一切正常,但我想优化它.如果我已经有超过1000个项目,GridView我想删除前300个项目,所以我不会遇到内存不足的问题.

问题是,当我从列表中删除前300个项目时(如实现中的clearIfNeeded()方法所示IOnRepositoryDataReturn),屏幕会移动.我不再看到我在移除之前看过的物品.

示例图片.如果images删除列表中的第一行(项目1-2),则显示情况.

  • 左图像 - 删除前的网格
  • 中心 - 删除后的网格(就像现在一样,删除顶部的项目将所有项目向上移动)
  • 对 - 我喜欢它的行为(删除某处的项目不会影响所看到的内容)

黑色方块代表了GridView.

在此输入图像描述

我想以某种方式调整观看位置GridView,所以我仍然会看到与删除前相同的图像.

布局xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ProgressBar
        android:id="@+id/ProgressSpinner"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintBottom_toBottomOf="@+id/GridView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/GridView" />

    <GridView
        android:id="@+id/GridView"
        android:layout_width="match_parent"
        android:layout_height="406dp"
        android:layout_marginBottom="8dp"
        android:numColumns="3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

    </GridView>
Run Code Online (Sandbox Code Playgroud)

是否有可能Grid View或者我应该寻找其他可能性?

Sho*_*uri 6

当GridView中已有超过1000个项目时,我想删除前300个项目,因此我不会遇到内存不足的问题.甚至可以使用Grid View,还是应该寻找其他可能性?

这是我的2美分.如果我理解正确,您的关注似乎是防止OutOfMemory异常并提高内存使用和性能.如果使用RecyclerView和实现照片网格GridLayoutManager,它将减少许多内存问题.你尝试删除屏幕外300项的方法,看起来非常麻烦且容易出错.以下摘自官方文档" 使用RecyclerView创建列表":

RecyclerView:

RecyclerView使用布局管理器在屏幕上定位各个项目,并确定何时重用用户不再可见的项目视图.要重用(或回收)视图,布局管理器可能会要求适配器使用与数据集不同的元素替换视图的内容.以这种方式回收视图可以避免创建不必要的视图或执行昂贵的findViewById()查找,从而提高性能.

GridLayoutManager:

GridLayoutManager将项目排列在二维网格中,就像棋盘上的方块一样.使用带有GridLayoutManager的RecyclerView提供的功能类似于较旧的GridView布局.

您可以在快速搜索中找到许多教程,例如:带有RecyclerView的Android GridLayoutManager