基于SQLite的通信录
实验目的
- 掌握SQLiteOpenHelper类结构
- 掌握基于SQLite数据库的应用开发过程
- 掌握ContentProvider发布数据的方法
- 掌握ContentResolver获取数据的方法
知识点回顾
Android系统中集成了SQLite数据库,并且为数据库的操作提供了相关的类和方法,便于没有数据库开发经验的开发者编写程序。另外,Android平台中得用ContentProvider机制来实现跨应用程序数据共享。一个应用程序可以通过ContentProvider来发布自己的数据,其他的应用程序可以通过ContentResolver来获取共享数据。
实验内容与步骤
1. 实现基于SQLite数据库通信录应用
运行结果视频所示。通过单击增加图标打开添加通信录界面,通过单击通信录中的各条信息可删除选中项。
【步骤】
(1) 建立数据库操作类DatabaseHelper,参考代码如下:
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String DB_NAME="MyRelation.db";
private static final String TABLE_NAME="relation";
private static final String CREATE_TABLE="create table relation(" +
"_id integer primary key autoincrement,name text,tel text,groupName text)";
private SQLiteDatabase db;
public DatabaseHelper(Context context)
{
super(context,DB_NAME,null,2);
}
@Override
public void onCreate(SQLiteDatabase db) {
this.db=db;
db.execSQL(CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
public void insert(ContentValues values){
SQLiteDatabase db=getWritableDatabase();
db.insert(TABLE_NAME,null,values);
db.close();
}
public void del(int id){
if(null==db)
db=getWritableDatabase();
db.delete(TABLE_NAME,"_id=?",new String[]{String.valueOf(id)});
}
public Cursor query(){
SQLiteDatabase db=getWritableDatabase();
Cursor cursor=db.query(TABLE_NAME,null,null,null,null,null,null);
return cursor;
}
public void close()
{
if(db!=null)
db.close();
}
}
(2) 创建主布局,参考步骤如下:
① 使用约束布局
② 添加文本框,并显示“通信录”,id为title
③ 添加列表框,并能选择“同学”、“同事”和“朋友”,id为listView
④ 添加图片按钮组件,并设置响应方法为“myClick”
(3) 修改主Activity文件MainActivity.java,参考代码如下:
public class MainActivity extends AppCompatActivity {
private ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView=(ListView)findViewById(R.id.listView);
getRelationFromDB();
}
private void getRelationFromDB()
{
final DatabaseHelper dbHelper=new DatabaseHelper(this);
Cursor cursor=dbHelper.query();
String[] from={"_id","name","tel","groupName"};
int[] to={R.id._id, R.id.name, R.id.tel, R.id.group};
SimpleCursorAdapter scadapter=new SimpleCursorAdapter(this,R.layout.relationlist,cursor,from,to);
listView.setAdapter(scadapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final long temp=id;
Log.d("temp", "onItemClick: ");
AlertDialog.Builder adBuilder=new AlertDialog.Builder(MainActivity.this);
adBuilder.setMessage("确认要删除记录吗?").setPositiveButton("确认",new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
dbHelper.del((int)temp);
Cursor cursor=dbHelper.query();
String[] from={"_id","name","tel","groupName"};
int[] to={R.id._id,R.id.name,R.id.tel,R.id.group};
SimpleCursorAdapter scadapter=new SimpleCursorAdapter(getApplicationContext(),R.layout.relationlist,cursor,from,to);
MainActivity.this.listView.setAdapter(scadapter);
}
}).setNegativeButton("取消",new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {}
});
AlertDialog aleraDialog=adBuilder.create();
aleraDialog.show();
}
});
dbHelper.close();
}
public void myClick(View view)
{
Intent intent=new Intent(MainActivity.this,AddRelationActivity.class);
startActivityForResult(intent,0x111);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==0x111&&resultCode==0x111)
getRelationFromDB();
}
}
(4) 创建列表视图布局文件relationlist.xml,参考步骤如下:
① 使用水平线性布局管理器
② 添加id文本框,id为_id,设置为不显示
③ 添加姓名文本框,id为name
④ 添加电话文本框,id为tel
⑤ 添加联系人群组文本框,id为group
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:descendantFocusability="blocksDescendants"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/_id"
android:text="id "
android:visibility="gone"
android:textSize="20sp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/name"
android:text="name"
android:textSize="20sp"
android:layout_weight="1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tel"
android:text="tel"
android:textSize="20sp"
android:layout_weight="1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/group"
android:text="group"
android:textSize="20sp" />
<CheckBox
android:id="@+id/select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false"
android:visibility="gone"/>
</LinearLayout>
(5) 创建增加联系人界面布局文件addrelation.xml,参考步骤如下:
① 使用竖直线性布局
② 添加输入姓名提示文本框
③ 添加姓名文本输入框,id为addName
④ 添加电话输入提示文本框
⑤ 添加电话输入框,id为addTel
⑥ 添加群组选择提示框
⑦ 添加群组选择下拉列表框,id为addGroup
⑧ 添加保存按钮,设置单击响应函数名为:save
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="姓名"
android:textSize="20sp"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/addName"
android:text="输入姓名"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="电话"
android:textSize="20sp"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/addTel"
android:text="输入电话号码"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="群组"
android:textSize="20sp"/>
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/addGroup"
android:entries="@array/array_group" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:onClick="save"
android:text="保存" />
</LinearLayout>
(6) 创建增加联系人界面Activity文件AddRelationActivity.java,参考代码如下:
public class AddRelationActivity extends Activity {
private EditText addName,addTel;
private Spinner addGroup;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.addrelation);
addName=(EditText) findViewById(R.id.addName);
addTel=(EditText) findViewById(R.id.addTel);
addGroup=(Spinner) findViewById(R.id.addGroup);
}
public void save(View view)
{
final ContentValues values=new ContentValues();
values.put("name",addName.getText().toString());
values.put("tel",addTel.getText().toString());
values.put("groupName",addGroup.getSelectedItem().toString());
final DatabaseHelper dbHelper=new DatabaseHelper(getApplicationContext());
final AlertDialog.Builder adBuilder=new AlertDialog.Builder(this);
adBuilder.setMessage("确认保存记录吗?").setPositiveButton("确认",new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
dbHelper.insert(values);
Intent intent=getIntent();
setResult(0x111,intent);
AddRelationActivity.this.finish();
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {}
});
AlertDialog aleraDialog=adBuilder.create();
aleraDialog.show();
}
}
(7) 在AndroidManifest.xml文件中添加AddRelationActivity界面应用
<activity android:name=".AddRelationActivity"
android:label="@string/app_name">
</activity>
2. 增加批量删除功能。
实现ListView单击和多选操作,在参考代码基础上新建ItemBean类,MyAdapter类。ItemBean用于保存联系人信息以及在多选中是否选中状态和是否展示复选框,MyAdapter适配器类用于对页面内容处理。
重写onItemClick和onItemLongClick方法,处理ListView不同的模式。
ItemBean.java
public class ItemBean {
private String id;
private String name;
private String telphone;
private String group;
private boolean isSelect;
private boolean isShowCheckBox;
public boolean isShowCheckBox() {
return isShowCheckBox;
}
public void setIsShowCheckBox(boolean isShowCheckBox) {
this.isShowCheckBox = isShowCheckBox;
}
public ItemBean(String id,String name,String tellphone,String group,boolean isSelect,boolean isShowCheckBox ){
this.id = id;
this.name = name;
this.telphone = tellphone;
this.group = group;
this.isSelect = isSelect;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTelphone() {
return telphone;
}
public void setTelphone(String telphone) {
this.telphone = telphone;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public boolean isSelect() {
return isSelect;
}
public void setIsSelect(boolean select) {
isSelect = select;
}
}
MyAdapter.java
public class MyAdapter extends BaseAdapter {
private List<ItemBean> list;
private LayoutInflater layoutInflater;
public MyAdapter(Context context, List<ItemBean> list){
this.list = list;
layoutInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = layoutInflater.inflate(R.layout.relationlist,null);
ViewHolder viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
}
ViewHolder viewHolder = (ViewHolder) convertView.getTag();
viewHolder.id.setText(list.get(position).getId());
viewHolder.name.setText(list.get(position).getName());
viewHolder.tel.setText(list.get(position).getTelphone());
viewHolder.group.setText(list.get(position).getGroup());
if(list.get(position).isShowCheckBox()){
viewHolder.checkBox.setVisibility(View.VISIBLE);
if(list.get(position).isSelect()){
viewHolder.checkBox.setChecked(true);
}else{
viewHolder.checkBox.setChecked(false);
}
}else{
viewHolder.checkBox.setVisibility(View.INVISIBLE);
}
return convertView;
}
public class ViewHolder {
public final TextView id;
public final TextView name;
public final TextView tel;
public final TextView group;
public final CheckBox checkBox;
public final View root;
public ViewHolder(View root) {
id = (TextView) root.findViewById(R.id._id);
name = (TextView) root.findViewById(R.id.name);
tel = (TextView) root.findViewById(R.id.tel);
group = (TextView) root.findViewById(R.id.group);
checkBox = (CheckBox) root.findViewById(R.id.select);
this.root = root;
}
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener, AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener {
private ListView listView;
private Boolean Flag = false;
private LinearLayout editbar;//按钮布局
private Button sure,cancel; //cancel是全选多选切换
private MyAdapter adapter;
private List<ItemBean> list;
private Boolean isLineaLayoutVisible = false;//标记按钮布局的显示
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView=(ListView)findViewById(R.id.listView);
editbar = (LinearLayout)findViewById(R.id.edit_bar);
sure = (Button)findViewById(R.id.delete);
cancel = (Button)findViewById(R.id.cancel);
sure.setOnClickListener(this);
cancel.setOnClickListener(this);
list = new ArrayList<ItemBean>();
getFromDB_bean();
}
private void getFromDB_bean() {
if(list != null) {
list.clear();
}
final DatabaseHelper dbHelper=new DatabaseHelper(this);
Cursor cursor=dbHelper.query();
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
String ids = cursor.getString(cursor.getColumnIndex("_id"));
String names = cursor.getString(cursor.getColumnIndex("name"));
String tels = cursor.getString(cursor.getColumnIndex("tel"));
String groups = cursor.getString(cursor.getColumnIndex("groupName"));
list.add(new ItemBean(ids,names,tels,groups,false,false));
}
adapter = new MyAdapter(this,list);
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
listView.setOnItemLongClickListener(this);
dbHelper.close();
}
//这一段没什么用了,但是onActivityResult()用到
private void getRelationFromDB()
{
final DatabaseHelper dbHelper=new DatabaseHelper(this);
Cursor cursor=dbHelper.query();
String[] from={"_id","name","tel","groupName"};
int[] to={R.id._id, R.id.name, R.id.tel, R.id.group};
SimpleCursorAdapter scadapter=new SimpleCursorAdapter(this,R.layout.relationlist,cursor,from,to);
listView.setAdapter(scadapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final long temp=id;
Log.d("temp", "onItemClick: ");
AlertDialog.Builder adBuilder=new AlertDialog.Builder(MainActivity.this);
adBuilder.setMessage("确认要删除记录吗?").setPositiveButton("确认",new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
dbHelper.del((int)temp);
Cursor cursor=dbHelper.query();
String[] from={"_id","name","tel","groupName"};
int[] to={R.id._id,R.id.name,R.id.tel,R.id.group};
SimpleCursorAdapter scadapter=new SimpleCursorAdapter(getApplicationContext(),R.layout.relationlist,cursor,from,to);
MainActivity.this.listView.setAdapter(scadapter);
}
}).setNegativeButton("取消",new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {}
});
AlertDialog aleraDialog=adBuilder.create();
aleraDialog.show();
}
});
dbHelper.close();
}
public void myClick(View view)
{
Intent intent=new Intent(MainActivity.this,AddRelationActivity.class);
startActivityForResult(intent,0x111);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==0x111&&resultCode==0x111)
getRelationFromDB();
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.delete:
String str = "";
for(ItemBean itemBean : list){
if(itemBean.isSelect()){
str+=itemBean.getName()+itemBean.getName()+"\n";
delete_one(itemBean);
}
}
if(str.equals("")){
Toast.makeText(this,"您没有选择",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this,str,Toast.LENGTH_SHORT).show();
}
break;
case R.id.cancel:
if(cancel.getText().equals("选择全部")){
for(ItemBean itemBean : list){
itemBean.setIsSelect(true);
}
cancel.setText("取消全部");
}else{
for(ItemBean itemBean : list){
itemBean.setIsSelect(false);
}
cancel.setText("选择全部");
}
adapter.notifyDataSetChanged();
break;
}
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(isLineaLayoutVisible){//当按钮布局显示时候才有权多项选择
list.get(position).setIsSelect(!list.get(position).isSelect());//向表中记录被选择的item
adapter.notifyDataSetChanged();//更新ListView
}
else{
ItemBean item = list.get(position);
delete_one(item);
}
}
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
try {
list.get(position).setIsSelect(true);//记录选择的item有机率不成功,我也不知道为啥,所以就用try
} catch (Exception e) {
e.printStackTrace();
list.get(position).setIsSelect(true);
}
for(ItemBean itemBean : list){
itemBean.setIsShowCheckBox(true);//将所有的Item的CheckBox设置为选择状态
}
adapter.notifyDataSetChanged();
editbar.setVisibility(View.VISIBLE);//长按item设置按钮布局为显示状态
isLineaLayoutVisible = true;
return true;
}
@Override
public void onBackPressed() {
if (isLineaLayoutVisible){
editbar.setVisibility(View.INVISIBLE);
isLineaLayoutVisible = false;
for(ItemBean itemBean : list){//按返回键时取消所有选择记录,同是吧按钮布局设置为不可见
itemBean.setIsShowCheckBox(false);
itemBean.setIsSelect(false);
}
adapter.notifyDataSetChanged();
}else {
super.onBackPressed();
}
}
public void delete_one(ItemBean item){
final DatabaseHelper dbHelper=new DatabaseHelper(this);
Cursor cursor=dbHelper.query();
//Toast.makeText(this,list.get(position).getName()+list.get(position).getTelphone(),Toast.LENGTH_SHORT).show();
final String temp=item.getId();
Log.d("temp", "onItemClick: ");
AlertDialog.Builder adBuilder=new AlertDialog.Builder(MainActivity.this);
adBuilder.setMessage("确认要删除记录吗?").setPositiveButton("确认",new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
dbHelper.del(Integer.parseInt(temp));
getFromDB_bean();
}
}).setNegativeButton("取消",new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {}
});
AlertDialog aleraDialog=adBuilder.create();
aleraDialog.show();
dbHelper.close();
}
}
实验问题
主要在参考代码基础上实现了ListView多选。
代码中仍然存在Bug,例如单击删除后再多选,出错;多选后再添加,出错。后续修改