Android 卡片浏览量和 XML 加载图像导致应用延迟
Android Cardviews and XML Loading Images Make App Lag
我在 XML 中使用了 4 个卡片视图,它们每个只加载一张图片和一个文本视图。不使用 RecyclerView 或任何动态的东西。
我的导航抽屉打开时有很多滞后,整个应用程序在添加卡片视图后滞后。有没有更好的方法来实现这些卡片视图?
这些只是嵌套在线性布局中。
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/app_bar_main"
android:orientation="vertical"
tools:context="com.example.jesse.apbiologystudyappv2.MainActivity">
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view_1_natural_selection"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
card_view:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="96dp"
android:scaleType="centerCrop"
android:src="@drawable/apple_tree" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Natural Selection and Evolution"
android:typeface="normal"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textColor="@color/colorTextIcons"
android:textSize="24dp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view_2_descent_and_ancestry"
android:layout_gravity="center"
android:layout_marginBottom="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="96dp"
android:scaleType="centerCrop"
android:src="@drawable/gravestones" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Descent and Ancestry"
android:typeface="normal"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textColor="@color/colorTextIcons"
android:textSize="24dp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view_3_speciation"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_marginBottom="16dp"
android:layout_height="wrap_content"
card_view:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="96dp"
android:scaleType="centerCrop"
android:src="@drawable/dinosaur" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Speciation and Extinction"
android:typeface="normal"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textColor="@color/colorTextIcons"
android:textSize="24dp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view_4_origin_of_life"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
card_view:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="96dp"
android:scaleType="centerCrop"
android:src="@drawable/bacteria" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Origin of Life"
android:typeface="normal"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textColor="@color/colorTextIcons"
android:textSize="24dp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
您也应该使用 RecyclerView 来管理内存。为此,您只需要一个 CardView。
activity_main.xml :
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/app_bar_main"
android:orientation="vertical"
tools:context="com.example.jesse.apbiologystudyappv2.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/lstActions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="1dp"
android:padding="0dp"/>
</LinearLayout>
cardview_item.xml:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view_1_natural_selection"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
card_view:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="96dp"
android:scaleType="centerCrop"
android:id="@+id/imgActoun" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/txtActoun"
android:typeface="normal"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textColor="@color/colorTextIcons"
android:textSize="24dp"/>
</RelativeLayout>
创建一个 class ActionItem.java 像这样:
public class ActionItem
{
private final int mTitleResID;
private final int mIconResID;
public ActionItem(int titleResID, int iconResID)
{
this.mTitleResID = titleResID;
this.mIconResID = iconResID;
}
public int getTitleResID()
{
return mTitleResID;
}
public int getIconResID()
{
return mIconResID;
}
}
MainActivity 中的 onCreateView 必须是这样的:
public View onCreateView(String name, Context context, AttributeSet attrs)
{
List<ActionItem> actionItems = new ArrayList<>();
actionItems.add(new ActionItem(R.string.NaturalSelectionAndEvolution, R.drawable.apple_tree));
actionItems.add(new ActionItem(R.string.DescentAndAncestry, R.drawable.gravestones));
RecyclerView lstActions = (RecyclerView) findViewById(R.id.lstActions);
ActionAdapter actionAdapter = new ActionAdapter(actionItems);
lstActions.setAdapter(actionAdapter);
return super.onCreateView(name, context, attrs);
}
像这样添加 ActionAdapter:
public class ActionAdapter extends RecyclerView.Adapter<ActionAdapter.ActionHolder>
{
private final List<ActionItem> mActionItems;
public ActionAdapter(List<ActionItem> actionItems)
{
this.mActionItems = actionItems;
}
@Override
public ActionHolder onCreateViewHolder(ViewGroup viewGroup, int i)
{
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
View itemView = inflater.inflate(R.layout.cardview_item, viewGroup, false);
return new ActionHolder(itemView);
}
@Override
public void onBindViewHolder(ActionHolder actionHolder, int position)
{
ActionItem actionItem = mActionItems.get(position);
actionHolder.mTxtTitle.setText(actionItem.getTitleResID());
actionHolder.mImgIcon.setImageResource(actionItem.getIconResID());
}
@Override
public int getItemCount()
{
return this.mActionItems.size();
}
public class ActionHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
protected final TextView mTxtTitle;
protected final ImageView mImgIcon;
public ActionHolder(View view)
{
super(view);
mImgIcon = (ImageView) view.findViewById(R.id.imgAction);
mTxtTitle = (TextView) view.findViewById(R.id.txtAction);
}
}
}
我对 Fred 的回答做了一些改动。而不是把这个
public View onCreateView(String name, Context context, AttributeSet attrs){
List<ActionItem> actionItems = new ArrayList<>();
actionItems.add(new ActionItem(R.string.NaturalSelectionAndEvolution, R.drawable.apple_tree));
actionItems.add(new ActionItem(R.string.DescentAndAncestry, R.drawable.gravestones));
RecyclerView lstActions = (RecyclerView) findViewById(R.id.lstActions);
ActionAdapter actionAdapter = new ActionAdapter(actionItems);
lstActions.setAdapter(actionAdapter);
return super.onCreateView(name, context, attrs);
}
在 onCreateView 中,我在 MainActivity 的 onCreate 中实现了它,并在 class:
的顶部放置了一些 declerations
private RecyclerView.LayoutManager mLayoutManager;
private List<ActionItem> actionItems = new ArrayList<>();
private RecyclerView listOfCards;
private ActionAdapter actionAdapter;
然而,我仍然遇到很多延迟,这是由于 XML 加载图像造成的。因此,我改用 Github 上可用的 Glide 依赖项。在ActionAdapter中,我添加了一个上下文需求,然后更改了onBindViewHolder。上下文要求是为了满足需要上下文的 Glide 方法。
public class ActionAdapter extends RecyclerView.Adapter<ActionAdapter.ActionHolder> {
private final List<ActionItem> mActionItems;
private Context mContext;
public ActionAdapter(List<ActionItem> actionItems, Context context) {
this.mActionItems = actionItems;
this.mContext = context;
}
@Override
public ActionHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
View itemView = inflater.inflate(R.layout.cardview_item, viewGroup, false);
return new ActionHolder(itemView);
}
@Override
public void onBindViewHolder(ActionHolder actionHolder, int position) {
ActionItem actionItem = mActionItems.get(position);
actionHolder.mTxtTitle.setText(actionItem.getTitleResID());
Glide.with(mContext).load(actionItem.getIconResID()).into(actionHolder.mImgIcon);
}
@Override
public int getItemCount() {
return this.mActionItems.size();
}
public class ActionHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
protected final TextView mTxtTitle;
protected final ImageView mImgIcon;
public ActionHolder(View view) {
super(view);
mImgIcon = (ImageView) view.findViewById(R.id.imgAction);
mTxtTitle = (TextView) view.findViewById(R.id.txtAction);
}
@Override
public void onClick(View v) {
//do something
}
}
}
如您所见,我从 onBindViewHolder 中删除了 actionHolder.mImgIcon .setText.... 并将其替换为 Glide 命令。这使得应用程序在启动时不会跳过任何帧,并且在打开导航抽屉时不会再产生延迟。原来延迟是由冗余 RelativeLayouts、XML 插入图片(而不是更有效的滑动)和不使用 RecyclerView 的组合产生的。
我在 XML 中使用了 4 个卡片视图,它们每个只加载一张图片和一个文本视图。不使用 RecyclerView 或任何动态的东西。 我的导航抽屉打开时有很多滞后,整个应用程序在添加卡片视图后滞后。有没有更好的方法来实现这些卡片视图? 这些只是嵌套在线性布局中。
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/app_bar_main"
android:orientation="vertical"
tools:context="com.example.jesse.apbiologystudyappv2.MainActivity">
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view_1_natural_selection"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
card_view:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="96dp"
android:scaleType="centerCrop"
android:src="@drawable/apple_tree" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Natural Selection and Evolution"
android:typeface="normal"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textColor="@color/colorTextIcons"
android:textSize="24dp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view_2_descent_and_ancestry"
android:layout_gravity="center"
android:layout_marginBottom="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="96dp"
android:scaleType="centerCrop"
android:src="@drawable/gravestones" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Descent and Ancestry"
android:typeface="normal"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textColor="@color/colorTextIcons"
android:textSize="24dp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view_3_speciation"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_marginBottom="16dp"
android:layout_height="wrap_content"
card_view:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="96dp"
android:scaleType="centerCrop"
android:src="@drawable/dinosaur" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Speciation and Extinction"
android:typeface="normal"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textColor="@color/colorTextIcons"
android:textSize="24dp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view_4_origin_of_life"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
card_view:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="96dp"
android:scaleType="centerCrop"
android:src="@drawable/bacteria" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Origin of Life"
android:typeface="normal"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textColor="@color/colorTextIcons"
android:textSize="24dp"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
您也应该使用 RecyclerView 来管理内存。为此,您只需要一个 CardView。
activity_main.xml :
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/app_bar_main"
android:orientation="vertical"
tools:context="com.example.jesse.apbiologystudyappv2.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/lstActions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="1dp"
android:padding="0dp"/>
</LinearLayout>
cardview_item.xml:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view_1_natural_selection"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
card_view:cardCornerRadius="8dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="96dp"
android:scaleType="centerCrop"
android:id="@+id/imgActoun" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/txtActoun"
android:typeface="normal"
android:layout_centerInParent="true"
android:textAlignment="center"
android:textColor="@color/colorTextIcons"
android:textSize="24dp"/>
</RelativeLayout>
创建一个 class ActionItem.java 像这样:
public class ActionItem
{
private final int mTitleResID;
private final int mIconResID;
public ActionItem(int titleResID, int iconResID)
{
this.mTitleResID = titleResID;
this.mIconResID = iconResID;
}
public int getTitleResID()
{
return mTitleResID;
}
public int getIconResID()
{
return mIconResID;
}
}
MainActivity 中的 onCreateView 必须是这样的:
public View onCreateView(String name, Context context, AttributeSet attrs)
{
List<ActionItem> actionItems = new ArrayList<>();
actionItems.add(new ActionItem(R.string.NaturalSelectionAndEvolution, R.drawable.apple_tree));
actionItems.add(new ActionItem(R.string.DescentAndAncestry, R.drawable.gravestones));
RecyclerView lstActions = (RecyclerView) findViewById(R.id.lstActions);
ActionAdapter actionAdapter = new ActionAdapter(actionItems);
lstActions.setAdapter(actionAdapter);
return super.onCreateView(name, context, attrs);
}
像这样添加 ActionAdapter:
public class ActionAdapter extends RecyclerView.Adapter<ActionAdapter.ActionHolder>
{
private final List<ActionItem> mActionItems;
public ActionAdapter(List<ActionItem> actionItems)
{
this.mActionItems = actionItems;
}
@Override
public ActionHolder onCreateViewHolder(ViewGroup viewGroup, int i)
{
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
View itemView = inflater.inflate(R.layout.cardview_item, viewGroup, false);
return new ActionHolder(itemView);
}
@Override
public void onBindViewHolder(ActionHolder actionHolder, int position)
{
ActionItem actionItem = mActionItems.get(position);
actionHolder.mTxtTitle.setText(actionItem.getTitleResID());
actionHolder.mImgIcon.setImageResource(actionItem.getIconResID());
}
@Override
public int getItemCount()
{
return this.mActionItems.size();
}
public class ActionHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
protected final TextView mTxtTitle;
protected final ImageView mImgIcon;
public ActionHolder(View view)
{
super(view);
mImgIcon = (ImageView) view.findViewById(R.id.imgAction);
mTxtTitle = (TextView) view.findViewById(R.id.txtAction);
}
}
}
我对 Fred 的回答做了一些改动。而不是把这个
public View onCreateView(String name, Context context, AttributeSet attrs){
List<ActionItem> actionItems = new ArrayList<>();
actionItems.add(new ActionItem(R.string.NaturalSelectionAndEvolution, R.drawable.apple_tree));
actionItems.add(new ActionItem(R.string.DescentAndAncestry, R.drawable.gravestones));
RecyclerView lstActions = (RecyclerView) findViewById(R.id.lstActions);
ActionAdapter actionAdapter = new ActionAdapter(actionItems);
lstActions.setAdapter(actionAdapter);
return super.onCreateView(name, context, attrs);
}
在 onCreateView 中,我在 MainActivity 的 onCreate 中实现了它,并在 class:
的顶部放置了一些 declerationsprivate RecyclerView.LayoutManager mLayoutManager;
private List<ActionItem> actionItems = new ArrayList<>();
private RecyclerView listOfCards;
private ActionAdapter actionAdapter;
然而,我仍然遇到很多延迟,这是由于 XML 加载图像造成的。因此,我改用 Github 上可用的 Glide 依赖项。在ActionAdapter中,我添加了一个上下文需求,然后更改了onBindViewHolder。上下文要求是为了满足需要上下文的 Glide 方法。
public class ActionAdapter extends RecyclerView.Adapter<ActionAdapter.ActionHolder> {
private final List<ActionItem> mActionItems;
private Context mContext;
public ActionAdapter(List<ActionItem> actionItems, Context context) {
this.mActionItems = actionItems;
this.mContext = context;
}
@Override
public ActionHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
View itemView = inflater.inflate(R.layout.cardview_item, viewGroup, false);
return new ActionHolder(itemView);
}
@Override
public void onBindViewHolder(ActionHolder actionHolder, int position) {
ActionItem actionItem = mActionItems.get(position);
actionHolder.mTxtTitle.setText(actionItem.getTitleResID());
Glide.with(mContext).load(actionItem.getIconResID()).into(actionHolder.mImgIcon);
}
@Override
public int getItemCount() {
return this.mActionItems.size();
}
public class ActionHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
protected final TextView mTxtTitle;
protected final ImageView mImgIcon;
public ActionHolder(View view) {
super(view);
mImgIcon = (ImageView) view.findViewById(R.id.imgAction);
mTxtTitle = (TextView) view.findViewById(R.id.txtAction);
}
@Override
public void onClick(View v) {
//do something
}
}
}
如您所见,我从 onBindViewHolder 中删除了 actionHolder.mImgIcon .setText.... 并将其替换为 Glide 命令。这使得应用程序在启动时不会跳过任何帧,并且在打开导航抽屉时不会再产生延迟。原来延迟是由冗余 RelativeLayouts、XML 插入图片(而不是更有效的滑动)和不使用 RecyclerView 的组合产生的。