gpt4 book ai didi

android - 在回收者 View 中加载大量项目

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:23:54 24 4
gpt4 key购买 nike

我在 fragment 中有一个回收器 View ,基本上我试图在回收器 View 中加载歌曲列表。回收器 View 的每一行都包含一个imageview(用于专辑封面)和textview (用于歌曲名称)。当数据集的大小很大时,我遇到了麻烦,即当歌曲太多时,回收器 View 滞后并且应用程序最终给出 ANR。我正在使用 Glide 在每一行的 ImageView 中加载专辑封面。谷歌音乐播放器如何能够毫无延迟地显示如此多的歌曲?

编辑:这是我的SongsFragment

public class SongsFragment extends Fragment {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
ProgressBar progressBar; // progress bar to show after every 30 items
NestedScrollView nestedScrollView; //for smooth scrolling of recyclerview as well as to detect the end of recyclerview
RecyclerView recyclerView;
ArrayList<Song> songMainList = new ArrayList<>(); //partial list in which items are added
ArrayList<Song> songAllList = new ArrayList<>(); //Complete List of songs
SongAdapter songsAdapter;
private LinearLayoutManager layoutManager;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_songs, container, false);

nestedScrollView = (NestedScrollView) rootView.findViewById(R.id.nestedScrollView);
progressBar = (ProgressBar) rootView.findViewById(R.id.progressBar);

String songJson = getActivity().getIntent().getStringExtra("songList");
songAllList = new Gson().fromJson(songJson, new TypeToken<ArrayList<Song>>() {
}.getType());
//Getting list of all songs in songAllList

if (songAllList.size() > 30) {
songMainList = new ArrayList<>(songAllList.subList(0,30));
} else {
songMainList = songAllList;
}

//if size of fetched songAllList>30 then add only 30 rows to songMainList

recyclerView = (RecyclerView) rootView.findViewById(R.id.songs);
int spanCount = 1; // 2 columns
int spacing = 4; // 50px
recyclerView.addItemDecoration(new GridItemDecoration(spanCount, spacing, true));
recyclerView.setHasFixedSize(true);
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
songsAdapter = new SongAdapter(getActivity(), songMainList, recyclerView);

nestedScrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
View view = (View) nestedScrollView.getChildAt(nestedScrollView.getChildCount() - 1);
int diff = (view.getBottom() - (nestedScrollView.getHeight() + nestedScrollView
.getScrollY()));

if (diff == 0) { //NestedScrollView scrolled to bottom
progressBar.setVisibility(View.VISIBLE); //show progressbar
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (songMainList.size() < songAllList.size()) {
int x = 0, y = 0;
if ((songAllList.size() - songMainList.size()) >= 30) {
x = songMainList.size();
y = x + 30;
} else {
x = songMainList.size();
y = x + songAllList.size() - songMainList.size();
}
for (int i = x; i < y; i++) {
songMainList.add(songAllList.get(i)); //Adding new items from songAllList to songMainList one by one
songsAdapter.notifyDataSetChanged();
}
}
progressBar.setVisibility(View.GONE);
}
}, 1500);


}
}
});
recyclerView.setAdapter(songsAdapter);


return rootView;
}
}

这是我的 RecyclerViewAdapterviewholder

public class SongAdapter extends RecyclerView.Adapter {

private List<Song> songsList;
private Context c;

private RecyclerView.ViewHolder holder;

public SongAdapter(Context context) {
mainActivityContext = context;
}

public SongAdapter(Context context, List<Song> songs, RecyclerView recyclerView) {
songsList = songs;
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
c = context;
}

public SongAdapter getInstance() {
return SongAdapter.this;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.song_list_row, parent, false);
return new SongViewHolder(view,c);
}

@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {

if (holder instanceof SongViewHolder) {
Song song = songsList.get(position);
this.holder = holder;

String name = song.getName();
String artist = song.getArtist();
String imagepath = song.getImagepath();

((SongViewHolder) holder).name.setText(name);

((SongViewHolder) holder).artist.setText(artist);

if (!imagepath.equalsIgnoreCase("no_image")) //if the album art has valid imagepath for this song

Glide.with(c).load(imagepath)
.centerCrop()
.into(((SongViewHolder) holder).iv);
else
((SongViewHolder) holder).iv.setImageResource(R.drawable.empty);

((SongViewHolder) holder).song = song;
}
}

@Override
public int getItemCount() {
return songsList.size();
}

static class SongViewHolder extends RecyclerView.ViewHolder{

ImageView iv;
TextView name, artist;
CardView songListCard;
private Context ctx;

private OnLongPressListener mListener;

SongViewHolder(View v, Context context) {
super(v);
this.ctx = context;
iv= (ImageView) v.findViewById(R.id.album_art);
name= (TextView) v.findViewById(R.id.name);
artist= (TextView) v.findViewById(R.id.artist_mini);
songListCard = (CardView) v.findViewById(R.id.song_list_card);
}
}

当只有 150-200 个项目时,recyclerview 工作正常,但当达到 600-700 个项目时,整个应用程序会变慢。这可能是因为我在 onBindViewHolder 中使用 glide 的方式?

最佳答案

排序答案:

LinearLayoutManager(context).apply { isAutoMeasureEnabled = false }
// or in Java
layoutManager.setAutoMeasureEnabled(false)

更新 2020.08.14

弃用 RecyclerView.LayoutManager#setAutoMeasureEnabled

此方法已在 API 级别 27.1.0 中弃用。LayoutManager 的实现者应该通过覆盖 isAutoMeasureEnabled()

来定义它是否使用 AutoMeasure

来自 RecyclerView.LayoutManager#setAutoMeasureEnabled() 的文档我们知道:

This method is usually called by the LayoutManager with value {@code true} if it wants to support WRAP_CONTENT

It works by calling {@link LayoutManager#onLayoutChildren(Recycler, State)} during an {@link RecyclerView#onMeasure(int, int)} call, then calculating desired dimensions based on children's positions.

如果我们设置 mAutoMeasure = true , 它会调用 LayoutManager#onLayoutChildren(Recycler, State)RecyclerView#onMeasure(int, int) 期间称呼。每个 subview 的 onMeasure()方法将被调用,这将花费太多时间。

enter image description here


我们来看一下LinearLayoutManager的构造函数

public LinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
setOrientation(orientation);
setReverseLayout(reverseLayout);
setAutoMeasureEnabled(true);
}

所以,在我们设置 mAutoMeasure = false 之后,一切都会好起来的。

enter image description here

关于android - 在回收者 View 中加载大量项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44347883/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com