Android(java)学习笔记186:对ListView等列表组件中数据进行增、删、改操作

时间:2022-01-23 07:32:01

1. ListView介绍

解决大量的相似的数据显示问题

采用了MVC模式:

M: model (数据模型)

V:  view  (显示的视图)

C: controller 控制器

入门案例:

acitivity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" > <ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/lv" /> </RelativeLayout>

MainActivity.java:

package com.itheima.listviewdemo;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView; public class MainActivity extends Activity {
//listview的视图 V view
private ListView lv; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.lv);
//设置数据适配器 数据控制器 adapter 相当于C controller
lv.setAdapter(new MyAdapter()); } private class MyAdapter extends BaseAdapter{ //控制器 /**
* 数据集合里面一共有多少条记录
*/
@Override
public int getCount() {
return 5000000;
}
/**
* 返回某个指定位置的view对象
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv = new TextView(MainActivity.this);
tv.setTextSize(25);
tv.setText("我是第"+position+"个被生出来的");
System.out.println("getview --positon:"+position); //M model 数据模型, textview
return tv;
}
@Override
public Object getItem(int position) {
return null;
} @Override
public long getItemId(int position) {
return 0;
}
} }

这里本来我们的MyAdapter是应该实现接口ListAdapter,但是实现接口ListAdapter要实现的方法太多,不太方便使用,于是必然衍生出更加方便的API接口,那这里就是BaseAdapter(还有其他的),我们追踪至源码,知道:BaseAdapter 是实现ListAdapter接口的。

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter { ………………}

通常默认实现类命名:

(1)BaseXXX

(2)BasicXXX

(3)SimpleXXX

(4)DefaultXXX

2. 由于像GridView、ListView等这样的列表组件是采用MVC模式的,因此不能直接通过列表组件对象对数据进行增、删、改操作。但是我们可以换个思路解决这个问题:

(1)首先我们直接对数据源中数据进行增、删、改操作

(2)然后调用BaseAdapter.notifyDataSetChanged方法通知列表组件进行数据更新。在调用notifyDataSetChanged方法的时候,系统会立刻调用这个BaseAdapter.getView()方法来获取当前显示的列表项的View对象,这样就更新的列表组件中显示的数据。

3. 下面通过一个案例来演示这个类似ListView列表组件数据修改的过程:

案例的运行效果图如下:

Android(java)学习笔记186:对ListView等列表组件中数据进行增、删、改操作

(1)首先还是布局文件,这里有主布局文件activity_main.xml,以及其他辅助的布局文件:

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" > <Button
android:id="@+id/add_id"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp"
android:layout_marginTop="5dp"
android:text="添加数据"
android:textColor="#99ff0000">
</Button> <Button
android:id="@+id/delete_id"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp"
android:layout_marginTop="5dp"
android:text="删除数据"
android:textColor="#99ff0000">
</Button> <Button
android:id="@+id/edit_id"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp"
android:layout_marginTop="5dp"
android:text="修改数据"
android:textColor="#99ff0000">
</Button> <Button
android:id="@+id/query_id"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp"
android:layout_marginTop="5dp"
android:text="查询数据"
android:textColor="#99ff0000">
</Button> <ListView
android:id="@+id/show_result"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</ListView> </LinearLayout>

主布局文件效果如下:

Android(java)学习笔记186:对ListView等列表组件中数据进行增、删、改操作

input_add.xml:添加数据

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" > <EditText
android:id="@+id/input_add_string"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true" >
</EditText> </LinearLayout>

input_delete.xml:删除数据

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" > <EditText
android:id="@+id/input_delete_number"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:digits="0123456789"
android:singleLine="true" >
</EditText> </LinearLayout>

input_edit.xml:修改数据

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" > <TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="输入要修改的索引" >
</TextView> <EditText
android:id="@+id/input_edit_number"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:digits="0123456789"
android:singleLine="true" >
</EditText> <TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="内容修改为" >
</TextView> <EditText
android:id="@+id/input_edit_string"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true" >
</EditText> </LinearLayout>

items.xml:列表子项目样式布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" > <TextView
android:id="@+id/viewspot"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:padding="6dip"
android:textColor="#88000000"
android:textSize="25dp" >
</TextView> <ImageView
android:id="@+id/add"
android:layout_width="100dip"
android:layout_height="wrap_content"
android:padding="10dip"
android:src="@drawable/right" >
</ImageView> </LinearLayout>

(2)主要的class文件,UpdateListViewActivity.java,如下:

package com.himi.updatelistview;

import java.util.ArrayList;
import java.util.HashMap; import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast; public class UpdateListViewActivity extends Activity { private Button addBtn;
private Button deleteBtn;
private Button editBtn;
private Button queryBtn;
private ListView listview;
// 数组
private SimpleAdapter listItemAdapter;
private ArrayList<HashMap<String, Object>> listItem = null; /** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // 获取控件
addBtn = (Button) findViewById(R.id.add_id);
deleteBtn = (Button) findViewById(R.id.delete_id);
editBtn = (Button) findViewById(R.id.edit_id);
queryBtn = (Button) findViewById(R.id.query_id);
listview = (ListView) findViewById(R.id.show_result); // 初始化数据
init(); // 设置控件事件监听
addBtn.setOnClickListener(addClick);
deleteBtn.setOnClickListener(deleteClick);
editBtn.setOnClickListener(editClick);
queryBtn.setOnClickListener(queryClick); } // 添加事件响应
OnClickListener addClick = new OnClickListener() { public void onClick(View v) {
// TODO Auto-generated method stub // 加载输入框的布局文件
LayoutInflater inflater = (LayoutInflater) UpdateListViewActivity.this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final LinearLayout layout = (LinearLayout) inflater.inflate(
R.layout.input_add, null); // 弹出的对话框 new AlertDialog.Builder(UpdateListViewActivity.this)
/* 弹出窗口的最上头文字 */
.setTitle("添加一条数据")
/* 设置弹出窗口的图式 */
.setIcon(android.R.drawable.ic_input_add)
/* 设置弹出窗口的信息 */
.setMessage("请输入添加的内容")
.setView(layout)
.setPositiveButton("确定",
new DialogInterface.OnClickListener() {
public void onClick(
DialogInterface dialoginterface, int i) { EditText inputStringr = (EditText) layout
.findViewById(R.id.input_add_string); String str = inputStringr.getText()
.toString(); if (str == null || str.equals("")) { Toast.makeText(getApplicationContext(),
"添加的内容不能为空", Toast.LENGTH_SHORT)
.show();
} else {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("viewspot", str);
map.put("add", R.drawable.right);
listItem.add(0, map);
// 如果在前面添加一条数据添加
// listItem.add(map);
listItemAdapter.notifyDataSetChanged();
Toast.makeText(
UpdateListViewActivity.this,
"添加的一条数据为:" + str + "",
Toast.LENGTH_SHORT).show(); } }
})
.setNegativeButton("取消",
new DialogInterface.OnClickListener() { /* 设置跳出窗口的返回事件 */
public void onClick(
DialogInterface dialoginterface, int i) {
Toast.makeText(UpdateListViewActivity.this,
"取消了删除数据", Toast.LENGTH_SHORT)
.show(); }
}).show(); }
}; // 删除事件响应
OnClickListener deleteClick = new OnClickListener() { public void onClick(View v) {
// TODO Auto-generated method stub /**
* listItem.clear();清空所有数据
*
* */ /*
* listItem.clear();
* listItemAdapter.notifyDataSetChanged();
*/ // 加载输入框的布局文件
LayoutInflater inflater = (LayoutInflater) UpdateListViewActivity.this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final LinearLayout layout = (LinearLayout) inflater.inflate(
R.layout.input_delete, null); // 弹出的对话框 new AlertDialog.Builder(UpdateListViewActivity.this)
/* 弹出窗口的最上头文字 */
.setTitle("删除一条数据")
/* 设置弹出窗口的图式 */
.setIcon(android.R.drawable.ic_input_delete)
/* 设置弹出窗口的信息 */
.setMessage("请输入删除的索引")
.setView(layout)
.setPositiveButton("确定",
new DialogInterface.OnClickListener() {
public void onClick(
DialogInterface dialoginterface, int i) { EditText inputNumber = (EditText) layout
.findViewById(R.id.input_delete_number); String str = inputNumber.getText()
.toString(); if (str == null || str.equals("")) { Toast.makeText(getApplicationContext(),
"请输入一个数字", Toast.LENGTH_SHORT)
.show();
} else {
int number = Integer.valueOf(str); int size = listItem.size(); // 判断数字是否超出数组索引范围
if (number >= size) {
Toast.makeText(
getApplicationContext(),
"没有找到删除的数据索引",
Toast.LENGTH_SHORT).show(); } else { String value = listItem.get(number)
.toString();
listItem.remove(number);
listItemAdapter
.notifyDataSetChanged();
Toast.makeText(
UpdateListViewActivity.this,
"删除的数据为:" + value + "",
Toast.LENGTH_SHORT).show(); }
} }
})
.setNegativeButton("取消",
new DialogInterface.OnClickListener() { /* 设置跳出窗口的返回事件 */
public void onClick(
DialogInterface dialoginterface, int i) {
Toast.makeText(UpdateListViewActivity.this,
"取消了删除数据", Toast.LENGTH_SHORT)
.show(); }
}).show(); }
};
// 修改事件响应
OnClickListener editClick = new OnClickListener() { public void onClick(View v) {
// TODO Auto-generated method stub
// 加载输入框的布局文件
LayoutInflater inflater = (LayoutInflater) UpdateListViewActivity.this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final LinearLayout layout = (LinearLayout) inflater.inflate(
R.layout.input_edit, null); // 弹出的对话框 new AlertDialog.Builder(UpdateListViewActivity.this)
/* 弹出窗口的最上头文字 */
.setTitle("修改一条数据")
/* 设置弹出窗口的图式 */
.setIcon(android.R.drawable.ic_dialog_alert)
/* 设置弹出窗口的信息 */
.setMessage("请输入修改的索引及内容")
.setView(layout)
.setPositiveButton("确定",
new DialogInterface.OnClickListener() {
public void onClick(
DialogInterface dialoginterface, int i) { EditText inputEditNumber = (EditText) layout
.findViewById(R.id.input_edit_number); String numberStr = inputEditNumber
.getText().toString(); EditText inputEditString = (EditText) layout
.findViewById(R.id.input_edit_string); String editStr = inputEditString.getText()
.toString(); if (numberStr == null
|| numberStr.equals("")) { Toast.makeText(getApplicationContext(),
"请输入要修改的索引", Toast.LENGTH_SHORT)
.show();
} else {
int number = Integer.valueOf(numberStr); int size = listItem.size(); // 判断数字是否超出数组索引范围
if (number >= size) {
Toast.makeText(
getApplicationContext(),
"没有找到修改的数据索引",
Toast.LENGTH_SHORT).show(); } else { HashMap<String, Object> map = new HashMap<String, Object>();
map.put("viewspot", editStr);
map.put("add", R.drawable.right); listItem.set(number, map);
listItemAdapter
.notifyDataSetChanged(); Toast.makeText(
UpdateListViewActivity.this,
"数据修改为:" + editStr + "",
Toast.LENGTH_SHORT).show(); }
} }
})
.setNegativeButton("取消",
new DialogInterface.OnClickListener() { /* 设置跳出窗口的返回事件 */
public void onClick(
DialogInterface dialoginterface, int i) {
Toast.makeText(UpdateListViewActivity.this,
"取消了修改数据", Toast.LENGTH_SHORT)
.show(); }
}).show(); }
}; // 查询事件响应
OnClickListener queryClick = new OnClickListener() { public void onClick(View v) {
// TODO Auto-generated method stub
// 查询数据
listItemAdapter.notifyDataSetChanged();
}
}; // 初始化数据
private void init() { listItem = new ArrayList<HashMap<String, Object>>();
for (int i = 0; i < 12; i++) {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("viewspot", "雪饮狂刀:" + i);
map.put("add", R.drawable.right);
listItem.add(map);
}
listItemAdapter = new SimpleAdapter(getApplicationContext(), listItem,// 数据源
R.layout.items, new String[] { "viewspot", "add" }, new int
[] {
R.id.viewspot, R.id.add });
listview.setAdapter(listItemAdapter); } }

 注意事项:

->1:Inflate()和findViewById()区分使用,以及两种之间的逻辑关系?

findViewById()只能找出当前布局中的组件,即setConentView()的那个layout里的组件.

如果你的Activity里用到别的layout,比如对话框layout,你还要设置这个layout上的其他组件的内容,你就必须用inflate()方法先将对话框的layout找出来,然后再用findViewById()找到它上面的其它组件。

->2:对数据源的增删改查,这只是对数据的操作而已,手机上面的ListView列表视图组件必须刷新显示,需要调用到notifyDataSetChanged()方法,就可以实现对listview数据的更新。如果涉及到线程,则需要在UI的线程更新。

->3:DialogInterface.OnClickListener接口实现方法Onclick()

public abstract void onClick (DialogInterface dialog, int which)  :对话框中的按钮按下时执行的方法.

参数: dialog  发生按钮按下事件的对话框(当一个Activity有多个对话框时,利用这个参数确定特定的对话框)

which   按下的按钮(例如:BUTTON1) 或按下的条目位置

对于which参数,如下:利用which参数按下的按钮(例如:BUTTON1) 或按下的条目位置

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Are you sure you want to exit?")
.setCancelable(false)
.setPositiveButton("Yes",this)
.setNegativeButton("No", this);
AlertDialog alert = builder.create();
alert.show();
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
Log.e("---------------", which + "");
switch (which) {
case -1:
Log.i("info", "你点击的YES~");
AndProgressActivity.this.finish();
break;
case -2:
Log.i("info", "你点击的NO~");
dialog.cancel();
break;
default:
break;
}
}