本文包括ListView的基本使用,convertview的机制,以及listview的刷新和局部刷新
1、ListView的基本使用
(1)页面布局文件
"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">
"@+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);
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
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 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 messageList;
private LayoutInflater layoutInflater;
public MessageAdapter(Context context, List 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);
}
}
}