滞后滚动问题:具有无限数量片段的 Viewpager
Laggy Scrolling Issue: Viewpager with Infinite number of fragments
我有一个 viewpager,其中根据数组列表的大小动态生成片段。除了卷轴,一切正常。滚动非常缓慢,会卡住 1-2 秒。
这是我的代码片段:
List<Fragment> fragments = getFragments(titleArray,
detailsArray, listArray);
pageAdapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
mPager.setAdapter(pageAdapter);
MyPageAdapter Class
private class MyPageAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
@Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
@Override
public CharSequence getPageTitle(int position) {
return titleArray.get(position);
}
@Override
public int getCount() {
return this.fragments.size();
}
}
getFragments()
private List<Fragment> getFragments(ArrayList<String> titleArray,
ArrayList<Map<String, String>> detailsArray, ArrayList<ItemData> listArray) {
List<Fragment> fList = new ArrayList<>();
int size = titleArray.size();
for (int i = 0; i < size; i++) {
if (detailsArray.size() > 0 && i == 0)
{
fList.add(SampRecFragment.newInstance(detailsArray));
} else {
if (listArray.get(i).getDetails().size() < 1)
{
fList.add(SampSingFragment.newInstance(i, listArray));
} else {
fList.add(SampMultFragment.newInstance(i, listArray));
}
}
}
return fList;
}
SampRecFragment.java(其他片段也类似)
public class SampRecFragment extends Fragment {
private CustomRecyclerVIew recyclerView;
private GridLayoutManager mLayoutManager;
private MyAdapter mAdapter;
ArrayList<Map<String, String>> detailsArray = new ArrayList<>();
public static SampRecFragment newInstance(ArrayList<Map<String, String>> index) {
SampRecFragment f = new SampRecFragment();
Bundle args = new Bundle();
args.putSerializable("index", index);
f.setArguments(args);
return f;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_recommended, null);
detailsArray = (ArrayList<Map<String, String>>) getArguments().getSerializable("index");
recyclerView = (CustomRecyclerVIew) view.findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(false);
mLayoutManager = new GridLayoutManager(getActivity() , 2);
// mLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
recyclerView.setLayoutManager(mLayoutManager);
mAdapter = new MyAdapter(detailsArray);
recyclerView.setAdapter(mAdapter);
mLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return isHeader(position) ? mLayoutManager.getSpanCount() : 1;
}
});
Log.i("SAMPREC", "onCreateView");
return view;
}
public boolean isHeader(int position) {
return position == 0;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.VHExpandItem> {
ArrayList<Map<String, String>> arrayList = new ArrayList<>();
public MyAdapter(ArrayList<Map<String, String>> arrayList) {
this.arrayList = arrayList;
}
@Override
public MyAdapter.VHExpandItem onCreateViewHolder(ViewGroup parent, int viewType) {
View v;
v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.restaurant_details_popular_item_view,
parent,
false);
return new VHExpandItem(v);
}
@Override
public void onBindViewHolder(final MyAdapter.VHExpandItem holder, final int position) {
final String media_url = arrayList.get(position).get("app_image");
holder.txt_main.setText(arrayList.get(position).get("item_name"));
holder.txt_price.setText("\u20B9 " + arrayList.get(position).get("price"));
Glide.with(getActivity())
.load(Uri.parse(media_url)).crossFade().into(holder.img_main);
final int[] count = {0};
final String quantity= ScoostyUtils.getItemQuantitySingle(getActivity(), arrayList.get(position).get("item_id"));
if(!quantity.equals(""))
{
holder.txt_badge.setVisibility(View.VISIBLE);
holder.txt_badge.setText(quantity);
}
holder.btn_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//
}
});
}
@Override
public int getItemCount() {
return arrayList.size();
}
class VHExpandItem extends RecyclerView.ViewHolder {
private final ImageView img_main;
private final TextView txt_main;
private final ImageView btn_add;
private final TextView txt_price;
private final TextView txt_badge;
public View View;
public VHExpandItem(View itemView) {
super(itemView);
View = itemView;
txt_badge = (TextView)itemView
.findViewById(R.id.txt_badge);
img_main = (ImageView) View
.findViewById(R.id.img_main);
txt_main = (TextView) View
.findViewById(R.id.txt_main);
btn_add = (ImageView) View.findViewById(R.id.btn_add);
txt_price = (TextView) View
.findViewById(R.id.txt_price);
}
}
}
}
LogCat
07-18 21:04:57.736 28362-28383/com.antfarm.scootsy W/art﹕ Suspending all threads took: 43.474ms
07-18 21:04:57.753 28362-28388/com.antfarm.scootsy W/art﹕ Suspending all threads took: 6.591ms
07-18 21:04:57.875 28362-28388/com.antfarm.scootsy I/art﹕ Background sticky concurrent mark sweep GC freed 176488(9MB) AllocSpace objects, 2(32KB) LOS objects, 17% free, 38MB/46MB, paused 11.019ms total 215.884ms
07-18 21:05:05.525 28362-28362/com.antfarm.scootsy I/SAMPMULTI﹕ onCreateView
07-18 21:05:07.716 28362-28362/com.antfarm.scootsy I/Choreographer﹕ Skipped 130 frames! The application may be doing too much work on its main thread.
07-18 21:05:08.042 28362-28362/com.antfarm.scootsy I/SAMPMULTI﹕ onCreateView
07-18 21:05:09.397 28362-28362/com.antfarm.scootsy I/SAMPMULTI﹕ onCreateView
07-18 21:05:10.355 28362-28362/com.antfarm.scootsy I/Choreographer﹕ Skipped 56 frames! The application may be doing too much work on its main thread.
07-18 21:05:32.093 28362-28362/com.antfarm.scootsy I/SAMPMULTI﹕ onCreateView
07-18 21:05:33.036 28362-28362/com.antfarm.scootsy I/Choreographer﹕ Skipped 55 frames! The application may be doing too much work on its main thread.
07-18 21:05:33.647 28362-28362/com.antfarm.scootsy I/SAMPMULTI﹕ onCreateView
07-18 21:05:34.530 28362-28362/com.antfarm.scootsy I/SAMPMULTI﹕ onCreateView
07-18 21:05:36.472 28362-28362/com.antfarm.scootsy I/Choreographer﹕ Skipped 115 frames! The application may be doing too much work on its main thread.
07-18 21:05:36.630 28362-28362/com.antfarm.scootsy I/SAMPMULTI﹕ onCreateView
07-18 21:05:38.526 28362-28362/com.antfarm.scootsy I/SAMPMULTI﹕ onCreateView
07-18 21:05:40.922 28362-28362/com.antfarm.scootsy I/art﹕ Explicit concurrent mark sweep GC freed 12569(805KB) AllocSpace objects, 2(11MB) LOS objects, 35% free, 28MB/44MB, paused 1.175ms total 62.130ms
请提出解决此问题的方法。谢谢。
我认为您应该针对回收站视图优化您的适配器。 PagerAdapter 不是罪魁祸首。涉及滚动的将是 Recycler View。
理想情况下,您应该使用 bean 类 而不是 ArrayList>,因为每次计算键上的代码都需要更多时间。
您还应该注意以下事项。
此外,每次您想要获取一些数据时,您都在调用 arrayList.get(position)
,调用它一次并在 bindView 中引用它并在每个地方使用该引用。
使您的视图层次结构尽可能扁平化,因为视图层次结构在 AdapterView 中非常重要,并且会根据嵌套级别对性能产生影响。
我有一个 viewpager,其中根据数组列表的大小动态生成片段。除了卷轴,一切正常。滚动非常缓慢,会卡住 1-2 秒。
这是我的代码片段:
List<Fragment> fragments = getFragments(titleArray,
detailsArray, listArray);
pageAdapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
mPager.setAdapter(pageAdapter);
MyPageAdapter Class
private class MyPageAdapter extends FragmentPagerAdapter {
private List<Fragment> fragments;
public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
@Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
@Override
public CharSequence getPageTitle(int position) {
return titleArray.get(position);
}
@Override
public int getCount() {
return this.fragments.size();
}
}
getFragments()
private List<Fragment> getFragments(ArrayList<String> titleArray,
ArrayList<Map<String, String>> detailsArray, ArrayList<ItemData> listArray) {
List<Fragment> fList = new ArrayList<>();
int size = titleArray.size();
for (int i = 0; i < size; i++) {
if (detailsArray.size() > 0 && i == 0)
{
fList.add(SampRecFragment.newInstance(detailsArray));
} else {
if (listArray.get(i).getDetails().size() < 1)
{
fList.add(SampSingFragment.newInstance(i, listArray));
} else {
fList.add(SampMultFragment.newInstance(i, listArray));
}
}
}
return fList;
}
SampRecFragment.java(其他片段也类似)
public class SampRecFragment extends Fragment {
private CustomRecyclerVIew recyclerView;
private GridLayoutManager mLayoutManager;
private MyAdapter mAdapter;
ArrayList<Map<String, String>> detailsArray = new ArrayList<>();
public static SampRecFragment newInstance(ArrayList<Map<String, String>> index) {
SampRecFragment f = new SampRecFragment();
Bundle args = new Bundle();
args.putSerializable("index", index);
f.setArguments(args);
return f;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_recommended, null);
detailsArray = (ArrayList<Map<String, String>>) getArguments().getSerializable("index");
recyclerView = (CustomRecyclerVIew) view.findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(false);
mLayoutManager = new GridLayoutManager(getActivity() , 2);
// mLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
recyclerView.setLayoutManager(mLayoutManager);
mAdapter = new MyAdapter(detailsArray);
recyclerView.setAdapter(mAdapter);
mLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return isHeader(position) ? mLayoutManager.getSpanCount() : 1;
}
});
Log.i("SAMPREC", "onCreateView");
return view;
}
public boolean isHeader(int position) {
return position == 0;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.VHExpandItem> {
ArrayList<Map<String, String>> arrayList = new ArrayList<>();
public MyAdapter(ArrayList<Map<String, String>> arrayList) {
this.arrayList = arrayList;
}
@Override
public MyAdapter.VHExpandItem onCreateViewHolder(ViewGroup parent, int viewType) {
View v;
v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.restaurant_details_popular_item_view,
parent,
false);
return new VHExpandItem(v);
}
@Override
public void onBindViewHolder(final MyAdapter.VHExpandItem holder, final int position) {
final String media_url = arrayList.get(position).get("app_image");
holder.txt_main.setText(arrayList.get(position).get("item_name"));
holder.txt_price.setText("\u20B9 " + arrayList.get(position).get("price"));
Glide.with(getActivity())
.load(Uri.parse(media_url)).crossFade().into(holder.img_main);
final int[] count = {0};
final String quantity= ScoostyUtils.getItemQuantitySingle(getActivity(), arrayList.get(position).get("item_id"));
if(!quantity.equals(""))
{
holder.txt_badge.setVisibility(View.VISIBLE);
holder.txt_badge.setText(quantity);
}
holder.btn_add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//
}
});
}
@Override
public int getItemCount() {
return arrayList.size();
}
class VHExpandItem extends RecyclerView.ViewHolder {
private final ImageView img_main;
private final TextView txt_main;
private final ImageView btn_add;
private final TextView txt_price;
private final TextView txt_badge;
public View View;
public VHExpandItem(View itemView) {
super(itemView);
View = itemView;
txt_badge = (TextView)itemView
.findViewById(R.id.txt_badge);
img_main = (ImageView) View
.findViewById(R.id.img_main);
txt_main = (TextView) View
.findViewById(R.id.txt_main);
btn_add = (ImageView) View.findViewById(R.id.btn_add);
txt_price = (TextView) View
.findViewById(R.id.txt_price);
}
}
}
}
LogCat
07-18 21:04:57.736 28362-28383/com.antfarm.scootsy W/art﹕ Suspending all threads took: 43.474ms
07-18 21:04:57.753 28362-28388/com.antfarm.scootsy W/art﹕ Suspending all threads took: 6.591ms
07-18 21:04:57.875 28362-28388/com.antfarm.scootsy I/art﹕ Background sticky concurrent mark sweep GC freed 176488(9MB) AllocSpace objects, 2(32KB) LOS objects, 17% free, 38MB/46MB, paused 11.019ms total 215.884ms
07-18 21:05:05.525 28362-28362/com.antfarm.scootsy I/SAMPMULTI﹕ onCreateView
07-18 21:05:07.716 28362-28362/com.antfarm.scootsy I/Choreographer﹕ Skipped 130 frames! The application may be doing too much work on its main thread.
07-18 21:05:08.042 28362-28362/com.antfarm.scootsy I/SAMPMULTI﹕ onCreateView
07-18 21:05:09.397 28362-28362/com.antfarm.scootsy I/SAMPMULTI﹕ onCreateView
07-18 21:05:10.355 28362-28362/com.antfarm.scootsy I/Choreographer﹕ Skipped 56 frames! The application may be doing too much work on its main thread.
07-18 21:05:32.093 28362-28362/com.antfarm.scootsy I/SAMPMULTI﹕ onCreateView
07-18 21:05:33.036 28362-28362/com.antfarm.scootsy I/Choreographer﹕ Skipped 55 frames! The application may be doing too much work on its main thread.
07-18 21:05:33.647 28362-28362/com.antfarm.scootsy I/SAMPMULTI﹕ onCreateView
07-18 21:05:34.530 28362-28362/com.antfarm.scootsy I/SAMPMULTI﹕ onCreateView
07-18 21:05:36.472 28362-28362/com.antfarm.scootsy I/Choreographer﹕ Skipped 115 frames! The application may be doing too much work on its main thread.
07-18 21:05:36.630 28362-28362/com.antfarm.scootsy I/SAMPMULTI﹕ onCreateView
07-18 21:05:38.526 28362-28362/com.antfarm.scootsy I/SAMPMULTI﹕ onCreateView
07-18 21:05:40.922 28362-28362/com.antfarm.scootsy I/art﹕ Explicit concurrent mark sweep GC freed 12569(805KB) AllocSpace objects, 2(11MB) LOS objects, 35% free, 28MB/44MB, paused 1.175ms total 62.130ms
请提出解决此问题的方法。谢谢。
我认为您应该针对回收站视图优化您的适配器。 PagerAdapter 不是罪魁祸首。涉及滚动的将是 Recycler View。
理想情况下,您应该使用 bean 类 而不是 ArrayList>,因为每次计算键上的代码都需要更多时间。 您还应该注意以下事项。
此外,每次您想要获取一些数据时,您都在调用 arrayList.get(position)
,调用它一次并在 bindView 中引用它并在每个地方使用该引用。
使您的视图层次结构尽可能扁平化,因为视图层次结构在 AdapterView 中非常重要,并且会根据嵌套级别对性能产生影响。