Android ListView加载多item布局及性能优化

转载请标明出处:http://blog.csdn.net/donkor_/article/details/53205414

前言:在开发过程中,遇到一些比较旧的项目,请求网络数据时,接口返回一长串的JSON字符串,其中包括各种不相关的数据。而我们又需要把这些数据一一对应写在同一个界面上,又需要分别展示在不同的布局上,这时候就需要用到ListView。

而当listview有大量的数据需要加载的时候,会占据大量内存,影响性能,这时候就需要按需填充并重新使用view来减少对象的创建。所以这里我们在展示多布局的同时,也对ListView加载性能优化。

废话讲了这么多,下面我们直接开始做个类似获取课程大纲的demo,先看一眼需要做的效果图界面:

这里写图片描述

需求是,B数据量会根据请求的数据而发生变化,A,B,C分别对应不同的布局。

下面直接上代码:

package com.donkor.demo;

import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;
import java.util.Map;

/**
 * @author donkor
 */
public class DetailListAdapter extends BaseAdapter {
    private Activity mContext;                        //运行上下文
    private List<Map<String, Object>> listItems;    //列表信息集合
    private LayoutInflater inflater;           //视图容器
    final int TYPE_1 = 0;
    final int TYPE_2 = 1;
    final int TYPE_3 = 2;

    public DetailListAdapter(Activity context, List<Map<String, Object>> listItems) {
        this.mContext = context;
        //创建视图容器并设置上下文
        inflater = LayoutInflater.from(context);   
        this.listItems = listItems;
    }

    @Override
    public int getCount() {
        return listItems.size();
    }

    @Override
    public Object getItem(int position) {
        return listItems.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    /**
     * 根据数据列表的position返回需要展示的layout的对应的type
     * type的值必须从0开始 
     */
    @Override
    public int getItemViewType(int position) {
        int p = position;
        //这里我们修改的是对应头item和底部item
        if (p == 0)
            return TYPE_1;
        else if (p == (listItems.size()-1))
            return TYPE_3;
        else
            return TYPE_2;
    }

    /**
     * 该方法返回多少个不同的布局
     */
    @Override
    public int getViewTypeCount() {
        return 3;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder1 holder1 = null;
        ViewHolder2 holder2 = null;
        ViewHolder3 holder3 = null;
        int type = getItemViewType(position);
        if (convertView == null) {
            inflater = LayoutInflater.from(mContext);
            // 按当前所需的样式,确定new的布局
            switch (type) {
                case TYPE_1:
                    convertView = inflater.inflate(R.layout.couese_detail_top,
                            parent, false);
                    holder1 = new ViewHolder1();
                    holder1.tvCourseTime = (TextView) convertView
                            .findViewById(R.id.tvCourseTime);
                    holder1.tvTeacherName = (TextView) convertView
                            .findViewById(R.id.tvTeacherName);
                    holder1.tvCourseObject = (TextView) convertView
                            .findViewById(R.id.tvCourseObject);

                    convertView.setTag(holder1);
                    break;
                case TYPE_2:
                    convertView = inflater.inflate(R.layout.course_list_item,
                            parent, false);
                    holder2 = new ViewHolder2();
                    holder2.tvCoursedescwap = (TextView) convertView
                            .findViewById(R.id.tvCoursedescwap);
                    convertView.setTag(holder2);
                    break;
                case TYPE_3:
                    convertView = inflater.inflate(R.layout.course_detail_bottom,
                            parent, false);
                    holder3 = new ViewHolder3();
                    holder3.ivCoursePic = (ImageView) convertView
                            .findViewById(R.id.ivCoursePic);
                    convertView.setTag(holder3);
                    break;
                default:
                    break;
            }
        } else {
            switch (type) {
                case TYPE_1:
                    holder1 = (ViewHolder1) convertView.getTag();
                    break;
                case TYPE_2:
                    holder2 = (ViewHolder2) convertView.getTag();
                    break;
                case TYPE_3:
                    holder3 = (ViewHolder3) convertView.getTag();
                    break;
            }
        }
        // 设置资源
        switch (type) {
            case TYPE_1:
                String courseTime = (String) listItems.get(position).get("courseTime");
                String teacherName = (String) listItems.get(position).get("teacherName");
                String courseObject = (String) listItems.get(position).get("courseObject");
                holder1.tvCourseTime.setText(courseTime);
                holder1.tvTeacherName.setText(teacherName);
                holder1.tvCourseObject.setText(courseObject);
                break;
            case TYPE_2:
                String author = (String) listItems.get(position).get("author");
                holder2.tvCoursedescwap.setText(author);
                break;
            case TYPE_3:
                holder3.ivCoursePic.setImageResource(R.mipmap.background2);
                break;
        }
        return convertView;
    }

    public class ViewHolder1 {
        TextView tvCourseTime, tvTeacherName, tvCourseObject;
    }

    public class ViewHolder2 {
        TextView tvCoursedescwap;
    }

    public class ViewHolder3 {
        ImageView ivCoursePic;
    }
}
※当处理一些耗时的资源加载的时候需要做到以下几点,以使你的加载更快更平滑
  1. 适配器在界面主线程中进行修改
  2. 可以在任何地方获取数据但应该在另外一个地方请求数据
  3. 在主界面的线程中提交适配器的变化并调用adapter的notifyDataSetChanged()方法修改UI


▲其他需要注意的地方
  • adapter中的getViewTypeCount():该方法返回多少个不同的布局
  • adapter中的getItemViewType(int
    position):根据数据列表的position返回需要展示的layout的对应的type。 type的值必须从0开始

Demo下载

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值