Android中ListView的使用(一)

本文包括ListView的基本使用,convertview的机制,以及listview的刷新和局部刷新
1、ListView的基本使用
(1)页面布局文件

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.netease.study.ui.listview.MainActivity">

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
</RelativeLayout>

(2)找到这个listview

ListView listView = (ListView) findViewById(R.id.list_view);

(3)设置Adapter

listView.setAdapter(adapter);

2、原理图
这里写图片描述

3、BaseAdapter中的方法

    //消息的数量
    @Override
    public int getCount() {
        return messageList.size();
    }
    //指定位置的message是什么
    @Override
    public Object getItem(int position) {
        return messageList.get(position);
    }

    //指定位置item的id是什么
    @Override
    public long getItemId(int position) {
        return position;
    }

    //当数据源有改动时,例如删除、添加,getItemId返回的positon就不稳定
    //当数据源没改动时,重写hasStableIds设置返回值为true,listView效率更高
    @Override
    public boolean hasStableIds() {
        return true;
    }

    //指定位置要显示的视图
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
//      此方法会忽略item布局中父布局的宽高,应使用layoutInflater.inflate(布局 parent, false);
//      View view = layoutInflater.inflate(R.layout.text_message_item, null);
        View view = layoutInflater.inflate(R.layout.text_message_item, parent, false);
        TextView textView = (TextView) view.findViewById(R.id.message_content);

        TextMessage message = messageList.get(position);
        textView.setText(message.getText());

        return view;
    }

4、ViewType的使用

(1)ViewType相关方法

    //获取ViewType的数量
    @Override
    public int getItemViewType(int position) {
        return super.getItemViewType(position);
    }
    //获取指定位置Item的ViewType
    @Override
    public int getViewTypeCount() {
        return super.getViewTypeCount();
    }

(2)ViewType示例代码

    private static final int ViewTypeCount = 2;
    private interface ViewType {
        int TEXT = 0;
        int IMAGE = 1;
    }

    private List<Object> messageList;

    public MessageAdapter(List<Object> messageList) {
        this.messageList = messageList;
    }

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

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());

        if (getItemViewType(position) == ViewType.TEXT) {
            if (convertView == null) {
                convertView = layoutInflater.inflate(R.layout.text_message_item, parent, false);
            }
            TextView textView = (TextView) convertView.findViewById(R.id.message_content);

            TextMessage textMessage = (TextMessage) messageList.get(position);
            textView.setText(textMessage.getText());
        } else {
            if (convertView == null) {
                convertView = layoutInflater.inflate(R.layout.image_message_item, parent, false);
            }
            ImageView imageView = (ImageView) convertView.findViewById(R.id.message_image);

            ImageMessage imageMessage = (ImageMessage) messageList.get(position);
            imageView.setImageResource(imageMessage.getImageResId());
        }

        return convertView;
    }

    @Override
    public int getItemViewType(int position) {
        if (getItem(position) instanceof TextMessage) {
            return ViewType.TEXT;
        } else {
            return ViewType.IMAGE;
        }
    }

    @Override
    public int getViewTypeCount() {
        return ViewTypeCount;
    }

5、convertview的机制
ListView中的RecycleBin的缓存机制,通过ViewType进行缓存,Type的种类就是getViewTypeCount的值,每个Type后都有一个ArrayList。
当要创建一个item时,就会去recyclebin里检查是否有相同的viewType,如果有就当作convertView传过来。如图所示
这里写图片描述
6、ViewHolder

    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;

        if (convertView == null) {
            convertView = layoutInflater.inflate(R.layout.text_message_item, parent, false);

            TextView time = (TextView) convertView.findViewById(R.id.message_time);
            TextView name = (TextView) convertView.findViewById(R.id.message_name);
            ImageView head = (ImageView) convertView.findViewById(R.id.message_head);
            TextView content = (TextView) convertView.findViewById(R.id.message_content);

            viewHolder = new ViewHolder(time, name, head, content);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        Message message = messageList.get(position);

        viewHolder.getTime().setText(message.getTime());

        viewHolder.getName().setText(message.getName());

        viewHolder.getHead().setImageResource(message.getHeadImageResId());

        viewHolder.getContent().setText(message.getContent());

        return convertView;
    }

    private static class ViewHolder {
        private TextView time;
        private TextView name;
        private ImageView head;
        private TextView content;

        public ViewHolder(TextView time, TextView name, ImageView head, TextView content) {
            this.time = time;
            this.name = name;
            this.head = head;
            this.content = content;
        }

        public TextView getTime() {
            return time;
        }

        public TextView getName() {
            return name;
        }

        public ImageView getHead() {
            return head;
        }

        public TextView getContent() {
            return content;
        }
    }

7、ListView刷新
(1)、修改数据源
(2)、notifyDataSetChanged

        final BaseAdapter adapter = new MessageAdapter(this, messageList);
        listView.setAdapter(adapter);

        findViewById(R.id.add_message).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String time = Calendar.getInstance().getTime().toLocaleString();
                messageList.add(0, new Message(
                        R.drawable.icon_contact,
                        "好友",
                        "我是文本消息",
                        time));

                adapter.notifyDataSetChanged();
            }
        });

        findViewById(R.id.remove_message).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (messageList.size() > 0) {
                    messageList.remove(0);
                    adapter.notifyDataSetChanged();
                }

            }
        });
    }

原理图
这里写图片描述
8、局部刷新
原理:找到需要刷新item的位置,刷新item数据。
Activity代码

public class MainActivity extends AppCompatActivity {
    private ListView listView;
    private List<Message> datas;
    private EditText modifyPosition;
    private View modifyButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        listView = (ListView) findViewById(R.id.list_view);

        datas = new ArrayList<>(100);
        for (int i = 0; i < 100; i++) {
            String time = Calendar.getInstance().getTime().toLocaleString();
            datas.add(new Message(
                    R.drawable.icon_contact,
                    "好友" + i,
                    "我是文本消息" + i,
                    time));
        }

        ListAdapter adapter = new MessageAdapter(this, datas);
        listView.setAdapter(adapter);

        modifyPosition = (EditText) findViewById(R.id.modify_position);
        modifyButton = findViewById(R.id.modify_message);

        modifyButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                try {
                    int position = Integer.parseInt(modifyPosition.getText().toString());

                    Message message = datas.get(position);
                    message.setContent("这是修改后的消息" + position);

                    partialRefresh(listView, position);
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                    Toast.makeText(MainActivity.this, "输入不合法", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    private void partialRefresh(ListView listView, int position) {
        if (position >= listView.getFirstVisiblePosition()
                && position <= listView.getLastVisiblePosition()) {
            int childIndex = position - listView.getFirstVisiblePosition();
            View child = listView.getChildAt(childIndex);

            if (child.getTag() instanceof ViewHolder) {
                ((ViewHolder) child.getTag()).refreshContent(datas.get(position).getContent());
            }
        }
    }
}

Adapter代码

public class MessageAdapter extends BaseAdapter {
    private List<Message> messageList;
    private LayoutInflater layoutInflater;

    public MessageAdapter(Context context, List<Message> messageList) {
        this.layoutInflater = LayoutInflater.from(context);
        this.messageList = messageList;
    }


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

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;

        if (convertView == null) {
            convertView = layoutInflater.inflate(R.layout.text_message_item, parent, false);

            TextView time = (TextView) convertView.findViewById(R.id.message_time);
            TextView name = (TextView) convertView.findViewById(R.id.message_name);
            ImageView head = (ImageView) convertView.findViewById(R.id.message_head);
            TextView content = (TextView) convertView.findViewById(R.id.message_content);

            viewHolder = new ViewHolder(time, name, head, content);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        Message message = messageList.get(position);

        viewHolder.getTime().setText(message.getTime());
        viewHolder.getName().setText(message.getName());
        viewHolder.getHead().setImageResource(message.getHeadImageResId());
        viewHolder.getContent().setText(message.getContent());

        return convertView;
    }

    public static class ViewHolder {
        private TextView time;
        private TextView name;
        private ImageView head;
        private TextView content;

        public ViewHolder(
                TextView time,
                TextView name,
                ImageView head,
                TextView content) {
            this.time = time;
            this.name = name;
            this.head = head;
            this.content = content;
        }

        public TextView getTime() {
            return time;
        }

        public TextView getName() {
            return name;
        }

        public ImageView getHead() {
            return head;
        }

        public TextView getContent() {
            return content;
        }

        public void refreshContent(String content) {
            this.content.setText(content);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值