转载请注明出处:明桑Android
这是作为上一篇Android 数据存储 如何搞定SQLite Database的实例练习,之所以单独列出来是因为除了数据库方面的知识,还涉及其它方面的知识,所以就写的详细点,啰嗦点。希望对初学者有所帮助。当然这个Demo比较简单,有很多可以改进的地方,但那不是这里探讨的重点,重点学习如何将SQLiteDatabase数据绑定到我们的界面!
本文代码地址:UseSQLitDatabase
我们要做一个简单的学生管理的demo,创建student.db,包括name,grade字段,实现增、删、改、查的功能;
实现效果:
1,界面分析
我们先不忙着码代码,先来看看这样一个简单的Demo**基本的界面结构**:
- 主界面是一个ListView用来显示学生信息,底部有两个Button,用来添加和查找学生信息;
- 点击**“添加”**Button,进入添加界面,输入姓名,分数,添加成功后返回主界面;
- 点击**“查找”**Button,弹出查找对话框,查找对话框此时包含一个EditView用来输入学生姓名和一个“查找”Button,当点击查找Button后,显示查找结果,如果查找结果为空,提示无此信息,如果不为空,点击结果可进入详细界面。
- 点击ListView Item可查看学生详细信息,在详细信息界面可对学生信息进行编辑修改和删除。
2,需要的的知识点:
- 自定义View的AlertDialog:因为我们的查找对话框需要我们自定义视图,不熟悉的请看Android常用实例—Alert Dialog的使用;
- 自定义Adapter的ListView:用来展示学生信息的ListView需要我们自定义Adapter将数据库中的数据填充到ListView。
- Toast用来提示消息:这个比较简单,用来提示一些信息,包括添加成功、删除成功等,Android消息提示:AlertDialog、Toast、Notification的使用;
- Activity之间的信息传递:我们需要将学生信息从一个Activity传递到另一个Activity,比如查看学生信息,或者添加成功后返回主界面,涉及到
Intent
和startActivityForResult()
等的使用。 - SQLiteDatabase的基本使用:这也是我们这个练习的重点,不熟悉的建议先看上篇文章Android 数据存储 如何搞定SQLite Database;
3,具体实现
创建项目后,根据上一篇文章所说,我们按照以下步骤来完成我们的Demo:
1,界面布局
通过界面分析我们可以看出:MainActivity用来显示所有学生列表信息,其他界面提供查看或者编辑修改以及删除的功能,在界面布局上非常相似,所以我们将它们放到同一个布局里面,只不过根据具体的情况,设置个某些控件的Visibility
属性为GONE
或者VISIBLE
;
主界面布局:res/layout/activity_main.xml
,包含一个ListView和两个Button
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/stduent_list"
android:layout_alignParentTop="true"
android:divider="#5ABC4F"
android:dividerHeight="1dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
<LinearLayout
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:layout_marginTop="3dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btn_add"
android:text="添 加"
android:textSize="25sp"
android:textColor="#ffffff"
android:gravity="center"
android:layout_marginRight="5dp"
android:background="#5ABC4F"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="45dp" />
<Button
android:id="@+id/btn_search"
android:text="查 找"
android:textSize="25sp"
android:textColor="#ffffff"
android:gravity="center"
android:layout_marginLeft="5dp"
android:background="#5ABC4F"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="45dp" />
</LinearLayout>
</RelativeLayout>
详细界面(增删改界面)布局:res/layout/student.xml
,在布局文件里面我们先将**查找**Button的Visibility属性设置为GONE,即不可见(注意区分:INVISIBLE为不可见但占据布局位置,GONE不可见且不占据位置)。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:src="@mipmap/boy"
android:id="@+id/student_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/student_name"
android:hint="输入姓名"
android:gravity="center"
android:textSize="20sp"
android:textColor="#5ABC4F"
android:layout_marginTop="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:id="@+id/student_grade"
android:hint="输入分数"
android:gravity="center"
android:textSize="15sp"
android:textColor="#5ABC4F"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/btn_change"
android:text="修 改"
android:textSize="25sp"
android:textColor="#ffffff"
android:gravity="center"
android:layout_margin="10dp"
android:background="#5ABC4F"
android:layout_width="match_parent"
android:layout_height="45dp" />
<Button
android:id="@+id/btn_delete"
android:text="删 除"
android:textSize="25sp"
android:textColor="#ffffff"
android:gravity="center"
android:layout_margin="10dp"
android:background="#5ABC4F"
android:layout_width="match_parent"
android:layout_height="45dp" />
<Button
android:id="@+id/btn_add_student"
android:text="添 加"
android:visibility="gone"
android:textSize="25sp"
android:textColor="#ffffff"
android:gravity="center"
android:layout_margin="10dp"
android:background="#5ABC4F"
android:layout_width="match_parent"
android:layout_height="45dp" />
</LinearLayout>
ListView Item布局:,用来显示学生头像,姓名和分数,res/layout/list_item.xml
布局效果:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:src="@mipmap/boy"
android:id="@+id/image"
android:layout_alignParentLeft="true"
android:padding="4dp"
android:layout_width="80dp"
android:layout_height="80dp" />
<TextView
android:id="@+id/name"
android:text="姓名"
android:textSize="20sp"
android:textColor="#5ABC4F"
android:layout_toRightOf="@+id/image"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/grade"
android:layout_toRightOf="@+id/image"
android:layout_below="@+id/name"
android:text="分数"
android:textSize="15sp"
android:textColor="#5ABC4F"
android:layout_marginTop="8dp"
android:layout_marginLeft="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
查找对话框布局:我们还需要为查找对话框做一个布局,res/layout/dialog_search.xml
,注意,刚开始搜索时,只显示EditView用来输入学生姓名,显示搜索结果时EditView不可见而显示一个ListView,所以布局中先将ListView的Visibility属性为GONE
布局效果:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/search_name"
android:gravity="center"
android:textSize="20sp"
android:textColor="#5ABC4F"
android:hint="学生姓名"
android:layout_width="wrap_content"
android:layout_margin="10dp"
android:layout_height="50dp" />
<ListView
android:id="@+id/search_result"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
<Button
android:id="@+id/btn_search_dialog"
android:layout_margin="10dp"
android:text="查 找"
android:textSize="25sp"
android:textColor="#ffffff"
android:gravity="center"
android:background="#5ABC4F"
android:layout_width="match_parent"
android:layout_height="45dp" />
</LinearLayout>
2,创建Student类:首先需要为我们存储的数据建立一个Model类,便于在使用中获取字段和对象。
Student.java
:为其提供构造函数和set\get方法;
public class Student implements Serializable{
private int id;
private String name;
private String grade;
public Student(){}
public Student(int id, String name, String grade) {
this.id = id;
this.name = name;
this.grade = grade;
}
public Student(String name, String grade) {
this.name = name;
this.grade = grade;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getGrade() {
return grade;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setGrade(String grade) {
this.grade = grade;
}
}
3,创建DatabaseHandler类:用来封装我们的数据库操作
DatabaseHandler.java
:编写构造函数,覆写onCreate(),onUpgrade()方法,以及提供增删改查student的方法:
addStudent(Student student)
;添加studentgetStudent(String name)
,通过name获取studentgetAllStudent()
;获取所有的studentgetStudentCounts()
;获取student数目updateStudent(Student student)
;更新studentdeleteStudent(Student student)
;删除student
public class DatabaseHandler extends SQLiteOpenHelper {
private static final String DATABASE_NAME="Test";
private static final String TABLE_NAME="student";
private static final int VERSION=1;
private static final String KEY_ID="id";
private static final String KEY_NAME="name";
private static final String KEY_GRADE="grade";
//建表语句
private static final String CREATE_TABLE="create table "+TABLE_NAME+"("+KEY_ID+
" integer primary key autoincrement,"+KEY_NAME+" text not null,"+
KEY_GRADE+" text not null);";
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, VERSION);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL(CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(sqLiteDatabase);
}
public void addStudent(Student student){
SQLiteDatabase db=this.getWritableDatabase();
//使用ContentValues添加数据
ContentValues values=new ContentValues();
values.put(KEY_NAME,student.getName());
values.put(KEY_GRADE,student.getGrade());
db.insert(TABLE_NAME, null, values);
db.close();
}
public Student getStudent(String name){
SQLiteDatabase db=this.getWritableDatabase();
//Cursor对象返回查询结果
Cursor cursor=db.query(TABLE_NAME,new String[]{KEY_ID,KEY_NAME,KEY_GRADE},
KEY_NAME+"=?",new String[]{name},null,null,null,null);
Student student=null;
//注意返回结果有可能为空
if(cursor.moveToFirst()){
student=new Student(cursor.getInt(0),cursor.getString(1), cursor.getString(2));
}
return student;
}
public int getStudentCounts(){
String selectQuery="SELECT * FROM "+TABLE_NAME;
SQLiteDatabase db=this.getReadableDatabase();
Cursor cursor=db.rawQuery(selectQuery,null);
cursor.close();
return cursor.getCount();
}
//查找所有student
public List<Student> getALllStudent(){
List<Student> studentList=new ArrayList<Student>();
String selectQuery="SELECT * FROM "+TABLE_NAME;
SQLiteDatabase db=this.getReadableDatabase();
Cursor cursor=db.rawQuery(selectQuery,null);
if(cursor.moveToFirst()){
do{
Student student=new Student();
student.setId(Integer.parseInt(cursor.getString(0)));
student.setName(cursor.getString(1));
student.setGrade(cursor.getString(2));
studentList.add(student);
}while(cursor.moveToNext());
}
return studentList;
}
//更新student
public int updateStudent(Student student){
SQLiteDatabase db=this.getWritableDatabase();
ContentValues values=new ContentValues();
values.put(KEY_NAME,student.getName());
values.put(KEY_GRADE,student.getGrade());
return db.update(TABLE_NAME,values,KEY_ID+"=?",new String[]{String.valueOf(student.getId())});
}
public void deleteStudent(Student student){
SQLiteDatabase db=this.getWritableDatabase();
db.delete(TABLE_NAME,KEY_ID+"=?",new String[]{String.valueOf(student.getId())});
db.close();
}
}
4,自定义Adapter:StudentAdapter:ListView需要自定义Adapter来显示视图,自定义Adapter扩展自BaseAdapter,覆写其中四个方法即可,其中getView()方法用来控制没个ListView item的具体显示。
public class StudentAdapter extends BaseAdapter {
private List<Student> students;
private Context context;
public StudentAdapter(Context context,List<Student> students) {
super();
this.students=students;
this.context=context;
}
@Override
public int getCount() {
return students.size();
}
@Override
public Object getItem(int i) {
return students.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
if(view==null){
view= LayoutInflater.from(context).inflate(R.layout.list_item,viewGroup,false);
}
ImageView imageView= (ImageView) view.findViewById(R.id.image);
TextView tvName= (TextView) view.findViewById(R.id.name);
TextView tvGrade= (TextView) view.findViewById(R.id.grade);
//随机为学生匹配头像
if(students.get(i).getId()%2==0)
{
imageView.setImageResource(R.mipmap.girl1);
}else{
imageView.setImageResource(R.mipmap.boy2);
}
tvName.setText("姓名 "+students.get(i).getName());
tvGrade.setText("分数 "+students.get(i).getGrade());
return view;
}
}
5,完成MainActivity:在这里要注意startActivityForResult()的使用,和为自定义View的AlertDialog添加事件监听。
public class MainActivity extends Activity implements View.OnClickListener{
private ListView students;
private StudentAdapter adapter;
private Button btnAdd,btnSearch;
private DatabaseHandler dbHandler;
private List<Student> studentList;
private SQLiteDatabase db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
students= (ListView) findViewById(R.id.stduent_list);
btnAdd= (Button) findViewById(R.id.btn_add);
btnSearch= (Button) findViewById(R.id.btn_search);
btnSearch.setOnClickListener(this);
btnAdd.setOnClickListener(this);
dbHandler=new DatabaseHandler(this);
//获取全部学生信息
studentList=dbHandler.getALllStudent();
adapter=new StudentAdapter(this,studentList);
students.setAdapter(adapter);
//点击ListView item跳转到详细界面
students.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent=new Intent(MainActivity.this,StudentActivity.class);
//注意这里的request是为了区分是通过什么跳转到详细界面的
intent.putExtra("request","Look");
intent.putExtra("id",studentList.get(i).getId());
intent.putExtra("name",studentList.get(i).getName());
intent.putExtra("grade",studentList.get(i).getGrade());
//
startActivityForResult(intent, 0);
}
});
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btn_add:
Intent i=new Intent(MainActivity.this,StudentActivity.class);
i.putExtra("request","Add");
startActivityForResult(i, 1);
break;
case R.id.btn_search:
AlertDialog.Builder builder=new AlertDialog.Builder(this);
//自定义View的Dialog
final LinearLayout searchView= (LinearLayout) getLayoutInflater().inflate(R.layout.dialog_search,null);
builder.setView(searchView);
final AlertDialog dialog=builder.create();
dialog.show();
//为自定义View的Dialog的控件添加事件监听。
final EditText searchName= (EditText) searchView.findViewById(R.id.search_name);
Button btnDialogSearch= (Button) searchView.findViewById(R.id.btn_search_dialog);
btnDialogSearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
searchName.setVisibility(View.GONE);
ListView list = (ListView) searchView.findViewById(R.id.search_result);
List<Student> resultList = new ArrayList<Student>();
final Student searchStudent = dbHandler.getStudent(searchName.getText().toString());
if (searchStudent != null) {
resultList.add(searchStudent);
StudentAdapter resultAdapter = new StudentAdapter(getApplicationContext(), resultList);
list.setAdapter(resultAdapter);
list.setVisibility(View.VISIBLE);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
dialog.dismiss();
Intent intent = new Intent(MainActivity.this, StudentActivity.class);
intent.putExtra("request", "Look");
intent.putExtra("id", searchStudent.getId());
intent.putExtra("name", searchStudent.getName());
intent.putExtra("grade", searchStudent.getGrade());
startActivityForResult(intent, 0);
}
});
} else {
//关闭Dialog
dialog.dismiss();
Toast.makeText(getApplicationContext(), "无此学生", Toast.LENGTH_SHORT).show();
}
}
});
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//根据返回的resultCode判断是通过哪种操作返回的,并提示相关信息;
switch (requestCode){
case 0:
if (resultCode==2)
Toast.makeText(this,"修改成功",Toast.LENGTH_SHORT).show();
if (resultCode==3)
Toast.makeText(this,"已删除",Toast.LENGTH_SHORT).show();
break;
case 1:
if (resultCode==RESULT_OK)
Toast.makeText(this,"添加成功",Toast.LENGTH_SHORT).show();
break;
}
/**
* 如果这里仅仅使用adapter.notifyDataSetChanged()是不会刷新界面ListView的,
* 因为此时adapter中传入的studentList并没有给刷新,即adapter也没有被刷新,所以你可以
* 重新获取studentList后再改变adapter,我这里通过调用onCreate()重新刷新了整个界面
*/
// studentList=dbHandler.getALllStudent();
// adapter=new StudentAdapter(this,studentList);
// students.setAdapter(adapter);
onCreate(null);
}
}
6,创建StudentActivity:用来展示详细信息和修改,删除。
public class StudentActivity extends Activity implements View.OnClickListener{
private EditText etName,etGrade;
private ImageView imageView;
private Button btnChange,btnDelete,btnAdd;
private int id;
private DatabaseHandler handler;
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.student);
etName= (EditText) findViewById(R.id.student_name);
etGrade= (EditText) findViewById(R.id.student_grade);
btnChange= (Button) findViewById(R.id.btn_change);
btnDelete= (Button) findViewById(R.id.btn_delete);
btnAdd= (Button) findViewById(R.id.btn_add_student);
imageView= (ImageView) findViewById(R.id.student_image);
handler=new DatabaseHandler(this);
//获取传递过来的intent
intent=getIntent();
//通过request判断,是通过那个Button点击进入的,之后隐藏或者显示相应的Button
String request=intent.getStringExtra("request");
switch (request){
//点击添加按钮进入的,则只显示btnAdd
case "Add":
btnChange.setVisibility(View.GONE);
btnDelete.setVisibility(View.GONE);
btnAdd.setVisibility(View.VISIBLE);
break;
//通过ListView Item进入的
case "Look":
id=intent.getExtras().getInt("id");
etName.setText(intent.getStringExtra("name"));
etGrade.setText(intent.getStringExtra("grade"));
//随机设定头像
if(id%2==0)
{
imageView.setImageResource(R.mipmap.girl1);
}else{
imageView.setImageResource(R.mipmap.boy2);
}
break;
}
btnAdd.setOnClickListener(this);
btnChange.setOnClickListener(this);
btnDelete.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btn_add_student:
Student newStudent=new Student(id,etName.getText().toString(),etGrade.getText().toString());
handler.addStudent(newStudent);
setResult(RESULT_OK, intent);
finish();
break;
case R.id.btn_change:
Student student=new Student(id,etName.getText().toString(),etGrade.getText().toString());
handler.updateStudent(student);
//这里设置resultCode是为了区分是修改后返回主界面的还是删除后返回主界面的。
setResult(2,intent);
finish();
break;
case R.id.btn_delete:
Student s=new Student(id,etName.getText().toString(),etGrade.getText().toString());
handler.deleteStudent(s);
setResult(3, intent);
finish();
break;
}
}
}
7,Manifest.xml:记得将StudentActivity添加进Manifest.xml
<activity android:name=".StudentActivity"/>
总结:
事实上,如果你对startActivityForResult()方法和Intent在Activity之间传递值等比较熟悉的话,这个Demo显得很简单,另外我们还用到了如何使用自定义View的ALertDialog和自定义View的ListView。还有一种比较常用的方法就是使用
CursorAdapter
来直接将数据库数据填充到ListView上,可以参考下面的文章。最后,对SQLiteDatabase在使用中的一些常用步骤需要了解,懂得如何封装我们所需要的操作,当然,最好自己能够动手实践,这样才能找到自己不熟悉或者出错的地方,下面几篇文章或许对你有所帮助~。
参考资料:
Populating a ListView with a CursorAdapter
Local Databases with SQLiteOpenHelper
Android SQLite database and content provider - Tutorial
- 微博: @明桑Android黑历史
- 邮箱: <[email protected]>
- 个人主页: 明桑战胜Android汪的黑历史
- 微信公众号: ITBird