美文网首页
2020-05-09-Android的ListView和Recy

2020-05-09-Android的ListView和Recy

作者: 耿望 | 来源:发表于2020-05-11 11:10 被阅读0次

滑动列表是最常见的UI界面,也常见卡顿问题。
今天看下两种列表的使用上面有什么区别。

ListView

ListView使用非常简单,但是也容易出现卡顿问题。默认情况下是比较耗时的。下图一帧的耗时是118毫秒。


1.PNG

如果对ConvertView进行复用,可以在一定程度上进行优化,避免多次inflate。下图优化后依然卡顿,时间是80毫秒。


2.PNG
如果增加一个ViewHolder缓存,就可以避免多次findViewById。下图优化后依然卡顿,时间是58毫秒。
3.PNG

最后,可以把一些耗时操作通过AsyncTask实现异步,下图优化后依然卡顿,时间是36毫秒。


4.PNG
public class MyAdapter extends ArrayAdapter<ApplicationInfo> {

    private static final String TAG = "MyAdapter";

    private PackageManager pms;
    private Context context;

    public MyAdapter(Context context, int resource) {
        super(context, resource);
        this.context = context;
        pms = context.getPackageManager();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Log.d(TAG, "getView position=" + position);
        ApplicationInfo info = getItem(position);
        View infoView = convertView;
        ViewHolder viewHolder;
        if (infoView == null) {
            infoView = LayoutInflater.from(context).inflate(R.layout.layout_list_item, parent, false);
            viewHolder = new ViewHolder();
            viewHolder.imageView = (ImageView)infoView.findViewById(R.id.img);
            viewHolder.textView = (TextView)infoView.findViewById(R.id.text);
            infoView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) infoView.getTag();
        }
        viewHolder.textView.setText(pms.getApplicationLabel(info));
        new LoadTask(viewHolder).execute(info);
        return infoView;
    }

    private static class ViewHolder {
        ImageView imageView;
        TextView textView;
    }

    private class LoadTask extends AsyncTask<ApplicationInfo, Void, Drawable> {

        private ViewHolder viewHolder;

        public LoadTask(ViewHolder viewHolder) {
            this.viewHolder = viewHolder;
        }

        @Override
        protected void onPostExecute(Drawable drawable) {
            viewHolder.imageView.setImageDrawable(drawable);
        }

        @Override
        protected Drawable doInBackground(ApplicationInfo... infos) {
            return pms.getApplicationIcon(infos[0]);
        }
    }
}

ListView有时会遇到瓶颈,上面的代码多次优化后依然卡顿,可以选择使用RecyclerView。

RecyclerView

RecyclerView可以实现更强大的功能,比如横向滑动,瀑布流布局等。同时默认有ViewHolder缓存机制,滑动更流畅。


5.PNG
public class HorizontalAdapter extends RecyclerView.Adapter<HorizontalAdapter.ViewHolder> {

    private static final String TAG = "HorizontalAdapter";

    private List<ApplicationInfo> list;
    private PackageManager pms;

    public HorizontalAdapter(List<ApplicationInfo> list) {
        this.list = list;
    }

    public void setContext(Context context) {
        pms = context.getPackageManager();
        Log.d(TAG, "getInstalledApplications size=" + list.size());
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        Log.d(TAG, "onCreateViewHolder");
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_horizontal_item,
                parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Log.d(TAG, "onBindViewHolder position=" + position);
        ApplicationInfo info = list.get(position);
        new LoadTask(holder).execute(info);
        String label = pms.getApplicationLabel(info).toString();
        if (label.length() > 6) {
            label = label.substring(0, 6);
        }
        holder.textView.setText(label);
    }

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

    public static class ViewHolder extends RecyclerView.ViewHolder {

        ImageView imageView;
        TextView textView;

        public ViewHolder(View itemView) {
            super(itemView);
            imageView = itemView.findViewById(R.id.img);
            textView = itemView.findViewById(R.id.text);
        }
    }

    private class LoadTask extends AsyncTask<ApplicationInfo, Void, Drawable> {

        private ViewHolder viewHolder;

        public LoadTask(ViewHolder viewHolder) {
            this.viewHolder = viewHolder;
        }

        @Override
        protected void onPostExecute(Drawable drawable) {
            viewHolder.imageView.setImageDrawable(drawable);
        }

        @Override
        protected Drawable doInBackground(ApplicationInfo... infos) {
            return pms.getApplicationIcon(infos[0]);
        }
    }
}

参考

android ListView 工作原理
ListView 的 Adapter 中getView方法的原理

相关文章

网友评论

      本文标题:2020-05-09-Android的ListView和Recy

      本文链接:https://www.haomeiwen.com/subject/ibtlnhtx.html