我在NestedScrollView中有Recyclerview。现在我有20个项目要在Recylerview中填充,但它显示的UI在其主线程上工作太多,并且不断被崩溃或被要求等待消息。任何建议都会受到赞赏。
UI:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/view_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<android.support.v7.widget.RecyclerView
android:id="@+id/recylerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@null"
android:orientation="horizontal" />
</android.support.v4.widget.NestedScrollView>
</RelativeLayout>
//List Item:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/view_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="4dp">
<RelativeLayout
android:id="@+id/rl_img"
android:layout_width="@dimen/img_wextra"
android:layout_height="wrap_content"
android:background="@drawable/rl_bg"
android:layout_alignBottom="@+id/ll_info"
android:layout_alignTop="@+id/tv_title"
android:orientation="horizontal">
<ImageView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:padding="4dp"
android:maxHeight="30dp"
android:maxWidth="30dp"
android:scaleType="fitXY" />
<ProgressBar
android:id="@+id/pb_img"
android:layout_width="@dimen/pb_size"
android:layout_height="@dimen/pb_size"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:visibility="visible"
/>
</RelativeLayout>
<ImageView
android:id="@+id/img_arrow"
android:layout_width="@dimen/frwd_size"
android:layout_height="@dimen/frwd_size"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="@drawable/icon_next" />
<me.grantland.widget.AutofitTextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/ll_info"
android:layout_toLeftOf="@+id/img_arrow"
android:textColor="@color/item_heading"
android:textSize="@dimen/text_size_medium" />
<me.grantland.widget.AutofitTextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/ll_info"
android:layout_below="@+id/tv_title"
android:layout_toLeftOf="@+id/img_arrow"
android:textSize="@dimen/text_size_small" />
<me.grantland.widget.AutofitTextView
android:id="@+id/tv_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/ll_info"
android:layout_below="@+id/tv_name"
android:layout_toLeftOf="@+id/img_arrow"
android:textSize="@dimen/text_size_small" />
<LinearLayout
android:id="@+id/ll_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/ll_btns"
android:layout_alignLeft="@+id/ll_btns"
android:layout_below="@+id/tv_loc"
android:layout_marginLeft="4dp"
android:layout_marginTop="4dp"
android:layout_toLeftOf="@+id/img_arrow"
android:layout_toRightOf="@+id/rl_img"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1.5"
android:textColor="@color/text_heading_color"
android:textSize="@dimen/text_size_small" />
<TextView
android:id="@+id/tv_title_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1.5"
android:textColor="@color/text_heading_color"
android:textSize="@dimen/text_size_small" />
<TextView
android:id="@+id/tv_title_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1.5"
android:textColor="@color/text_heading_color"
android:textSize="@dimen/text_size_small" />
<TextView
android:id="@+id/tv_title_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1.5"
android:textColor="@color/text_heading_color"
android:textSize="@dimen/text_size_small" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_userName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:maxLines="1"
android:text="0000000"
android:textColor="@color/colorBlack"
android:textSize="@dimen/text_size_small" />
<TextView
android:id="@+id/tv_userdes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:maxLines="1"
android:text="0000000"
android:textColor="@color/colorBlack"
android:textSize="@dimen/text_size_small" />
<TextView
android:id="@+id/tv_usernum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:maxLines="1"
android:text="0000000"
android:textColor="@color/colorBlack"
android:textSize="@dimen/text_size_small" />
<TextView
android:id="@+id/tv_userrating"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight=".5"
android:maxLines="1"
android:text="0000000"
android:textColor="@color/colorBlack"
android:textSize="@dimen/text_size_small" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
Code:
recylerview.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
recylerview.setItemAnimator(new DefaultItemAnimator());
recylerview.setNestedScrollingEnabled(false);
recylerview.addItemDecoration(new SimpleDividerItemDecoration(getActivity()));
ItemOffsetDecoration itemDecoration = new ItemOffsetDecoration(getActivity(), R.dimen.item_offset_mini);
recylerview.addItemDecoration(itemDecoration);
recylerview.setAdapter(itemAdapter);
//Adapter
public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ItemViewHolder> {
public interface OnItemClickListener {
void onItemClick(ItemModel item);
}
private List<ItemModel> items;
private Context context;
private OnItemClickListener listener;
public ItemAdapter(Context context, List<ItemModel> items, OnItemClickListener listener) {
this.items = items;
this.context = context;
this.listener = listener;
}
@Override
public ItemAdapter.ItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
return new ItemViewHolder(view);
}
@Override
public void onBindViewHolder(ItemAdapter.ItemViewHolder viewHolder, int i) {
viewHolder.bind(items.get(i), listener);
viewHolder.tv_title.setText(items.get(i).getTitle());
viewHolder.tv_name.setText(items.get(i).getItemTitle());
viewHolder.tv_loc.setText(items.get(i).getItemLoc());
viewHolder.tv_name.setTextColor(Color.BLACK);
viewHolder.tv_loc.setTextColor(Color.BLACK);
viewHolder.tv_userName.setText(items.get(i).getUserName());
viewHolder.tv_userdes.setText(items.get(i).getUserDes());
FragmentUtils.setBOLDFont(viewHolder.tv_title);
FragmentUtils.setFont(viewHolder.tv_name);
FragmentUtils.setFont(viewHolder.tv_loc);
FragmentUtils.setFont(viewHolder.tv_title_1);
FragmentUtils.setFont(viewHolder.tv_title_2);
FragmentUtils.setFont(viewHolder.tv_title_3);
FragmentUtils.setFont(viewHolder.tv_title_4);
// Loading profile image
if (items.get(i).getImage().size() != 0) {
Drawable myIcon = context.getResources().getDrawable( R.drawable.not_found );
ImageUtils.displayImageFromUrl(context, items.get(i).getImage().get(0).getThumbnail(), viewHolder.img,myIcon, new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@android.support.annotation.Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
viewHolder.pb_img.setVisibility(View.GONE);
return false;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
viewHolder.pb_img.setVisibility(View.GONE);
return false;
}
});
} else {
ImageUtils.displayImageFromResources(context, viewHolder.img, R.drawable.not_found);
viewHolder.pb_img.setVisibility(View.GONE);
}
}
@Override
public int getItemCount() {
return items.size();
}
public class ItemViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.tv_title)
public TextView tv_title;
@BindView(R.id.tv_name)
public TextView tv_name;
@BindView(R.id.tv_des)
public TextView tv_des;
@BindView(R.id.tv_userName)
public TextView tv_userName;
@BindView(R.id.tv_userLoc)
public TextView tv_userLoc;
@BindView(R.id.img)
public ImageView img;
@BindView(R.id.pb_img)
public ProgressBar pb_img;
@BindView(R.id.tv_title_1)
public TextView tv_title_1;
@BindView(R.id.tv_title_2)
public TextView tv_title_2;
@BindView(R.id.tv_title_3)
public TextView tv_title_3;
@BindView(R.id.tv_title_4)
public TextView tv_title_4;
public ItemViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
public void bind(final ItemModel item, final OnItemClickListener listener) {
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onItemClick(item);
}
});
}
}
}
///Log:
01-23 10:14:19.343 11462-11467/com.app I/art: Do full code cache collection, code=252KB, data=241KB
01-23 10:14:19.344 11462-11467/com.app I/art: Starting a blocking GC JitCodeCache
01-23 10:14:19.344 11462-11467/com.app I/art: After code cache collection, code=213KB, data=181KB
01-23 10:14:20.212 11462-11467/com.app I/art: Do partial code cache collection, code=250KB, data=207KB
01-23 10:14:20.213 11462-11467/com.app I/art: After code cache collection, code=250KB, data=207KB
01-23 10:14:20.213 11462-11467/com.app I/art: Increasing code cache capacity to 1024KB
01-23 10:14:27.706 11462-11462/com.app I/Choreographer: Skipped 505 frames! The application may be doing too much work on its main thread.
01-23 10:14:35.519 11462-11462/com.app I/Choreographer: Skipped 464 frames! The application may be doing too much work on its main thread.
01-23 10:14:43.019 11462-11462/com.app I/Choreographer: Skipped 449 frames! The application may be doing too much work on its main thread.
01-23 10:14:50.488 11462-11462/com.app I/Choreographer: Skipped 447 frames! The application may be doing too much work on its main thread.
答案 0 :(得分:4)
这种情况正在发生,因为<RecyclerView>
标记的wrap_content
标记为<NestedScrollView>
。这意味着您的1000个项目中的每一个都将为其创建一个视图持有者,从而导致数千个视图被充气和填充。我想即使你等待所有这一切发生,你的应用程序也会因OutOfMemoryError
而崩溃。
显而易见的问题是,您希望在NestedScrollView中使用RecyclerView。如果你有这个:
<RelativeLayout
...>
<android.support.v7.widget.RecyclerView
android:id="@+id/recylerview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
RecyclerView实际上可以执行视图回收,您的应用应该会响应。
答案 1 :(得分:2)
是的@Ben是正确的RecyclerView
是VERTICAL
而且wrap_content
加上1000个项目在NestedScrollView
尝试在RecyclerView
或Relativelayout
Linearlayout
另外,我可以看到你已经match_parent
给了ImageView
并再次以这种方式在父布局中给出了高度,每次调整大小都是UI中的额外负载
另请注意,maxWidth
和maxHeight
无法使用match_parent
<RelativeLayout
android:id="@+id/rl_img"
android:layout_width="@dimen/img_wextra"
android:layout_height="wrap_content"
android:background="@drawable/rl_bg"
android:layout_alignBottom="@+id/ll_info"
android:layout_alignTop="@+id/tv_title"
android:orientation="horizontal">
<ImageView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:padding="4dp"
android:maxHeight="30dp"
android:maxWidth="30dp"
android:scaleType="fitXY" />
对placeholder
使用Progressbar
而不是Imageview
,还有一件事情更好。