java - 具有无限滚动优化的 GridView
问题描述
我创建了一个简单的应用程序,它从 Pixabay上获取图像,然后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();
}
}
负责数据处理的代码:
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;
}
});
}
}
一切正常,但我想优化它。当已经有超过 1000 个项目时,GridView
我想删除前 300 个项目,这样我就不会遇到内存不足的问题。
问题是,当我简单地从列表中删除前 300 个项目时(如实现中的clearIfNeeded()
方法所示IOnRepositoryDataReturn
),屏幕会移动。我不再看到我在删除之前看到的项目。
示例图像。images
如果从列表中删除第一行(第 1-2 项)的情况。
- 左图 - 移除前的网格
- center - 移除后的网格(现在,移除顶部的项目会向上移动所有项目)
- 对 - 我希望它如何表现(在某处移除项目不会影响所看到的)
黑色方块代表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>
甚至有可能Grid View
还是我应该寻找其他可能性?
解决方案
当 GridView 中已经有超过 1000 个项目时,我想删除前 300 个项目,这样我就不会遇到内存不足的问题。网格视图甚至可能吗?还是我应该寻找其他可能性?
这是我的 2 美分。如果我理解正确,您的担忧似乎是防止 OutOfMemory 异常并提高内存使用率和性能。如果您使用RecyclerView
and实现照片网格GridLayoutManager
,它将减少您的许多内存问题。您尝试删除屏幕外 300 个项目的方法似乎非常麻烦且容易出错。以下是标题为使用 RecyclerView 创建列表的官方文档的摘录:
回收站视图:
RecyclerView 使用布局管理器来定位屏幕上的各个项目,并确定何时重用用户不再可见的项目视图。为了重用(或回收)视图,布局管理器可能会要求适配器用数据集中的不同元素替换视图的内容。以这种方式回收视图通过避免创建不必要的视图或执行昂贵的 findViewById() 查找来提高性能。
网格布局管理器:
GridLayoutManager 将项目排列在二维网格中,就像棋盘上的正方形一样。将 RecyclerView 与 GridLayoutManager 一起使用可提供类似于旧 GridView 布局的功能。
您可以在快速搜索中找到许多相关教程,例如:Android GridLayoutManager with RecyclerView
推荐阅读
- html - 绝对位置 div 垂直间隔不均匀
- javascript - 几个数组清空
- javascript - 面临向对象 JS 添加属性的问题
- html - 包裹图像的 Flexbox 锚标签具有巨大的宽度
- javascript - React-router v4,URL更改但组件不呈现
- javascript - 无渲染组件中的 Vue 绑定引用
- sql - 同时从两个不同的程序插入同一个数据库表
- javascript - 如何在javascript,Angular中获取视频文件的二进制数据
- mysql - MySQL比较不同的值以防万一
- html - 在网站前面使用反向代理将 http 请求从 iframe 中重定向到网站