问题
我有一个recyclerview,显示从SQL数据库加载的歌曲列表。我的问题是,当我向下滚动它移动一些元素,然后动画就像它触及底部。然后我可以继续滚动,但它会使滚动起伏并且非常明显。奇怪的是它只会在我向下滚动时发生。如果我向上滚动,我可以顺利地从列表的底部到顶部。向下滚动时,它会回收一些元素,然后突然停止,并且在它停止之前它似乎不是一个设定量。滚动速度也无关紧要,即使速度很慢也会这样做。
我制作了一个自定义字母选择器,允许跳转到列表中的特定部分工作正常,但我禁用它以查看是否导致问题,但不是。
视频
前几个卷轴正在下降,你可以看到它停止了“列表底部”动画。然后我可以继续滚动。最后一个卷轴正在上升,它慢慢停止,并且不显示“列表顶部”动画。
https://www.youtube.com/watch?v=0-Tr8DDGJCc&feature=youtu.be
代码
片段
public class LibraryFragment extends Fragment {
TextView mTitle;
private RecyclerView itemsView;
private SideSelector selector;
private LibraryListAdapter adapter;
private AppDatabase mDatabase;
private Song.ModeType mMode = null;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_library, container, false);
mTitle = (TextView) view.findViewById(R.id.title);
mTitle.setText("LIBRARY");
itemsView = (RecyclerView) view.findViewById(R.id.library_items);
selector = (SideSelector) view.findViewById(R.id.side_selector);
adapter = new LibraryListAdapter();
itemsView.setLayoutManager(new LinearLayoutManager(getContext()));
itemsView.setAdapter(adapter);
/*itemsView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int visiblePos = ((LinearLayoutManager)itemsView.getLayoutManager()).findFirstVisibleItemPosition();
int section = adapter.getSectionForPosition(visiblePos);
selector.setCurrentSection(section);
}
});
selector.setView(itemsView);*/
mDatabase = Room.databaseBuilder(getContext().getApplicationContext(),
AppDatabase.class, "database-name").build();
setMenu();
return view;
}
public void setSongs(String title) {
adapter.clearList();
mTitle.setText(title);
selector.setVisibility(View.VISIBLE);
getSongs();
}
public void setMenu() {
ArrayList<ListItem> data = new ArrayList<>();
mTitle.setText("LIBRARY");
data.add(new MenuInfo(new View.OnClickListener() {
@Override
public void onClick(View v) {
setSongs("ALL");
}
}, "All"));
data.add(new MenuInfo(new View.OnClickListener() {
@Override
public void onClick(View v) {
setSongs("MUSIC & MUSICALS");
}
}, "Music & Musicals"));
data.add(new MenuInfo(new View.OnClickListener() {
@Override
public void onClick(View v) {
setSongs("MOVIES & TELEVISION");
}
}, "Movies & Television"));
data.add(new MenuInfo(new View.OnClickListener() {
@Override
public void onClick(View v) {
setSongs("HISTORY & LITERATURE");
}
}, "History & Literature"));
selector.setVisibility(View.GONE);
adapter.setListItems(data);
}
private void getSongs() {
new AsyncTask<Void, Void, List<Song>>() {
@Override
protected List<Song> doInBackground(Void... params) {
final Song.Dao songDao = mDatabase.songDao();
return songDao.getAll();
}
@Override
protected void onPostExecute(List<Song> songs) {
for (Song song : songs) {
adapter.addListItem(new MediaInfo(song));
}
adapter.notifyDataSetChanged();
}
}.execute();
}
}
适配器的
public class LibraryListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements SectionIndexer {
public static String[] ALPHABET = new String[]{"#", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
private List<ListItem> mDataArray = new ArrayList<ListItem>();
public void setListItems(List<ListItem> items) {
mDataArray = items;
notifyDataSetChanged();
}
public void addListItem(ListItem item) {
mDataArray.add(item);
}
public void clearList() {
mDataArray.clear();
notifyDataSetChanged();
}
public void notifyChange() {
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
if(mDataArray.size() > position && position >= 0) {
return mDataArray.get(position).getType();
}
return -1;
}
@Override
public int getSectionForPosition(int position) {
int section = 0;
if(mDataArray.size() > position && position >= 0) {
for(String letter : ALPHABET) {
if(mDataArray.get(position).getName().startsWith(letter)) {
break;
}
section++;
}
}
return section;
}
@Override
public Object[] getSections() {
return ALPHABET;
}
@Override
public int getPositionForSection(int sectionIndex) {
if(sectionIndex < 0) { sectionIndex = 0; }
if(sectionIndex >= ALPHABET.length) { sectionIndex = ALPHABET.length - 1; }
int position = 0;
for (ListItem info : mDataArray) {
if(info instanceof MediaInfo) {
if (((MediaInfo) info).getName().charAt(0) >= ALPHABET[sectionIndex].charAt(0)) {
break;
}
}
position++;
}
return position;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View item = null;
switch (viewType) {
case ListItem.VIEW_TYPE_MEDIA:
item = LayoutInflater.from(parent.getContext()).inflate(R.layout.library_media_item, parent, false);
return new MediaItemViewHolder(item);
case ListItem.VIEW_TYPE_MENU_ITEM:
item = LayoutInflater.from(parent.getContext()).inflate(R.layout.library_menu_item, parent, false);
return new MenuItemViewHolder(item);
default:
return null;
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
holder.itemView.setOnClickListener(mDataArray.get(position).getOnClickListener());
switch (holder.getItemViewType()) {
case ListItem.VIEW_TYPE_MEDIA:
MediaItemViewHolder holder_media = (MediaItemViewHolder) holder;
holder_media.setTitle(mDataArray.get(position).getName());
holder_media.setArtist(((MediaInfo) mDataArray.get(position)).getSong().getArtist());
holder_media.setType(((MediaInfo) mDataArray.get(position)).getSong().getMode());
break;
case ListItem.VIEW_TYPE_MENU_ITEM:
MenuItemViewHolder holder_menu = (MenuItemViewHolder) holder;
holder_menu.setName(mDataArray.get(position).getName());
break;
}
}
@Override
public int getItemCount() {
return mDataArray.size();
}
public static class MediaItemViewHolder extends RecyclerView.ViewHolder {
public TextView mTitleView;
public TextView mArtistView;
public ImageView mImageView;
public MediaItemViewHolder(View v) {
super(v); // done this way instead of view tagging
mTitleView = (TextView) v.findViewById(R.id.library_item_title);
mArtistView = (TextView) v.findViewById(R.id.library_item_artist);
mImageView = (ImageView) v.findViewById(R.id.library_item_icon);
}
public void setTitle(String title) {
mTitleView.setText(title);
}
public void setArtist(String artist) {
mArtistView.setText(artist);
}
public void setType(Song.ModeType type) {
switch (type) {
case BOOK:
mImageView.setImageResource(R.drawable.ic_book);
break;
case MOVIE:
mImageView.setImageResource(R.drawable.ic_movie);
break;
case SONG:
mImageView.setImageResource(R.drawable.ic_music);
break;
}
}
}
public static class MenuItemViewHolder extends RecyclerView.ViewHolder {
public TextView mNameView;
public MenuItemViewHolder(View v) {
super(v); // done this way instead of view tagging
mNameView = (TextView) v.findViewById(R.id.name);
}
public void setName(String name) {
mNameView.setText(name);
}
}
}
布局的
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="35dp"
android:paddingRight="35dp"
android:paddingTop="25dp"
android:paddingBottom="25dp">
<TextView
android:id="@+id/title"
android:text="TITLE"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="serif"
android:textSize="24dp"
android:textColor="@android:color/black" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/library_items"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toStartOf="@+id/side_selector"
android:background="@drawable/border_top_gray"
android:nestedScrollingEnabled="true"
android:layout_marginTop="10dp"></android.support.v7.widget.RecyclerView>
<com.beneville.grandfatherclock.views.SideSelector
android:id="@+id/side_selector"
android:layout_width="30dp"
android:layout_height="match_parent"
android:layout_alignParentRight="true" />
</RelativeLayout>
</LinearLayout>
答案 0 :(得分:0)
Android中的不稳定滚动是应用程序在更新UI的主应用程序线程上花费了太多时间。对于RecyclerView,这意味着在onBindViewHolder()或onCreateViewHolder()中可能需要花费太多时间。
以下是关于如何使滚动顺利成为黄油的好方法:6 ways to make your Android app scroll faster than the wind