我创建了一个简单的应用程序,该应用程序可以从png中获取图像,然后以无限滚动的方式在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;
}
});
}
}
一切正常,但我想对其进行优化。当GridView
中已经有1000多个项目时,我想删除前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>
使用Grid View
甚至有可能还是我应该寻找其他可能性?
答案 0 :(得分:6)
当GridView中已经有1000多个项目时,我想删除前300个项目,因此不会遇到内存不足的问题。 Grid View甚至有可能还是我应该寻找其他可能性?
这是我的2美分。如果我理解正确,那么您的担心似乎是在防止OutOfMemory异常并提高内存使用率和性能。如果您使用RecyclerView
和GridLayoutManager
来实现照片网格,则可以减少很多内存问题。您尝试删除屏幕外的300个项目的方法似乎很麻烦并且容易出错。这是摘自Create a List with RecyclerView的官方文档的摘录:
RecyclerView:
RecyclerView使用布局管理器将单个项目放置在屏幕上,并确定何时重新使用用户不再可见的项目视图。为了重用(或回收)视图,布局管理器可能会要求适配器用与数据集不同的元素替换视图的内容。 以这种方式回收视图可避免创建不必要的视图或执行昂贵的findViewById()查找,从而提高了性能。
GridLayoutManager:
GridLayoutManager将项目排列在二维网格中,如棋盘上的正方形。将RecyclerView与GridLayoutManager一起使用可提供类似旧版GridView布局的功能。
您可以通过快速搜索找到许多有关此的教程,例如:Android GridLayoutManager with RecyclerView
答案 1 :(得分:1)
您可以通过以下方法对此进行优化:
要滚动到底部,我不再使用ScrollListener以获得更好的性能。我将为您提供另一种选择:
致电onBindViewHolder
:
@Override
受保护的void onBindContentViewHolder(RecyclerView.ViewHolder viewHolder,int位置){
if(0!= position && position == getItemCount()-1 && null!= mCallback){
mCallback.onReachLastItem();
}
}
使您的片段或活动实现AdapterCallback加载更多数据。