Android SQLite增删改查基本用法,通讯录实现
在Android的项目开发中,都会用到数据库,SQLite作为本地数据库,是一定要会的。Android团队封装了很多对SQLite操作的API。我这里自己写了一个Demo来总结一下SQLit的基本使用方法。
先上截图
Android专门提供了一个SQLiteOpenHelper帮助类,可以非常简单地对数据库进行创建和升级。
首先创建数据库,我们这里创建一个类继承SQLiteOpenHelper类,并重写onCreate()和onUpgrade()方法:
import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;/** * Created by lenovo on 2018/10/14. */public class DatabaseUtil extends SQLiteOpenHelper { private static final String DATABASE_NAME = "PhoneBook.db"; //数据库名 private static final int DATABASE_VERSION = 1; //数据库版本号 public DatabaseUtil(Context context){ super(context,DATABASE_NAME,null,DATABASE_VERSION); } /** * 创建数据库 * */ @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { createTable(sqLiteDatabase); } /** * 建立数据表 * */ private void createTable(SQLiteDatabase db){ db.execSQL("create table UserInfo(" + "id integer primary key autoincrement," + "userName text," + "userPhone text)"); } /** * 升级数据库 * */ @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { }}
这个类主要用于建立数据库和更新数据库
实例化这个类的时候构造函数传入上下文,并继承父类构造函数,数据库名称和版本号都已经写成了常量。onCreate()方法在创建时和创建后只会调用一次,所以在这里面创建一次数据表就行了,而onUpgrade()方法只有在数据库版本号大于上次传入的值时调用,用于对数据库进行更新操作,如新建表,更改列等。
创建一个Utildao类专门对数据库进行增删改查操作,主要目的是与逻辑代码分开便于代码维护,附上代码:
import android.content.ContentValues;import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import com.example.lenovo.work.entity.User;import java.util.ArrayList;import java.util.List;/** * Created by lenovo on 2018/10/16. */public class UtilDao { private DatabaseUtil du; private SQLiteDatabase db; public UtilDao(Context context){ du = new DatabaseUtil(context); db = du.getWritableDatabase(); } /** * 添加数据 * */ public void addData(String tableName,String[] key,String[] values){ ContentValues contentValues = new ContentValues(); for(int i = 0; i < key.length; i ++){ contentValues.put(key[i],values[i]); } db.insert(tableName,null,contentValues); contentValues.clear(); } /** * 删除数据 * */ public int delData(String where,String[] values){ int del_data; del_data = db.delete("UserInfo",where,values); return del_data; } /** * 修改数据 * */ public void update(String[] values){ db.execSQL("update UserInfo set userName=?,userPhone=? where userName=? ",values); } /** * 查询数据 * */ public List inquireData(){ List list = new ArrayList<>(); Cursor cursor = db.rawQuery("select userName,userPhone" + " from UserInfo",null); while(cursor.moveToNext()){ String name = cursor.getString(0); String phone = cursor.getString(1); User user = new User(); user.setName(name); user.setPhone(phone); list.add(user); } return list; } /** * 关闭数据库连接 * */ public void getClose(){ if(db != null){ db.close(); } }}
我们先调用帮助类的getWritableDatabase()方法,获取可写入的权限。
Android有两种方法对数据进行增删改查操作,一种是Android封装好的方法,另一种是通用的直接执行SQL语句的方法,我这里为了方便部分使用了面向对象方法,部分是直接执行SQL语句的。使用execSQL()方法直接执行SQL语句没有返回值且容易出错,所以我推荐使用Android自带封装好的方法操作数据库。
添加:
这里调用了帮助类的insert方法,第一个参数传入表名,第二个参数暂时用不到传入null,第三个参数传入ContentValues对象,ContentValues对象提供了put()方法重载,用于向ContentValues中添加数据。
/** * 添加数据 * */ public void addData(String tableName,String[] key,String[] values){ ContentValues contentValues = new ContentValues(); for(int i = 0; i < key.length; i ++){ contentValues.put(key[i],values[i]); } db.insert(tableName,null,contentValues); contentValues.clear(); }
删除:
调用delete方法,第一个参数传入表名,第二个参数写条件where语句,通常写列名,不写的话删除所有行,第三个传入列名对应的值,最后返回删除的行数。
/** * 删除数据 * */ public int delData(String where,String[] values){ int del_data; del_data = db.delete("UserInfo",where,values); return del_data; }
修改:
我这里调用了execSQL方法直接写SQL语句,封装的方法为update请自行搜索,这里第一个值是SQL语句没什么好说的,第二个值为传入的条件值,对应SQL语句里的"?"通配符。
/** * 修改数据 * */ public void update(String[] values){ db.execSQL("update UserInfo set userName=?,userPhone=? where userName=? ",values); }
查询:
查询代码就比较多了,先调用rawQuery方法查询出结果,再把值赋给Cursor对象,它是一个游标,通过while判断它指向的行下面是否还有数据,若有则把当前行的值存储到User实体类里,然后添加到List数组链表中,循环下一次。这里用到List是因为这需要返回给前台的ListView做数据源。
/** * 查询数据 * */ public List inquireData(){ List list = new ArrayList<>(); Cursor cursor = db.rawQuery("select userName,userPhone" + " from UserInfo",null); while(cursor.moveToNext()){ String name = cursor.getString(0); String phone = cursor.getString(1); User user = new User(); user.setName(name); user.setPhone(phone); list.add(user); } return list; }
到这里数据访问层和dao层就写好了,接下来实现功能。
因为UtilDao这个类里面的数据库操作方法以后会经常用到,如果每次都 new 一个对象来使用的话会很麻烦,所以我这里使用了MyApplication类来将 UtilDao 类设为全局变量且只有一个实例,这样就方便多了。
import android.app.Application;import com.example.lenovo.work.dbutil.UtilDao;/** * Created by lenovo on 2018/10/16. */public class MyApplication extends Application { private UtilDao dao; /** * 创建时调用 * */ @Override public void onCreate() { super.onCreate(); dao = new UtilDao(this); } /** * 后台进程终止,前台程序需要内存时调用此方法,用于释放内存 * 用于关闭数据库连接 * */ @Override public void onLowMemory() { super.onLowMemory(); dao.getClose(); } public UtilDao getDao() { return dao; }}
因为Application组件优先于Activity,在程序运行时最先创建且只创建一次。需要在AndroidManifest.xml里标签里添加name属性,这点很重要!!!不然程序崩溃。
android:name=".MyApplication"
布局很简单,这里我就不过多的解释,自行理解:
<?xml version="1.0" encoding="utf-8"?>
我们先建一个实体类,用于存储用户信息,作为ListView 的数据源:
public class User { private String name; private String phone; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; }}
ListView子布局(item):
<?xml version="1.0" encoding="utf-8"?>
ListView数据适配器:
import android.content.Context;import android.support.annotation.NonNull;import android.support.annotation.Nullable;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ArrayAdapter;import android.widget.TextView;import com.example.lenovo.work.R;import com.example.lenovo.work.entity.User;import java.util.List;/** * Created by lenovo on 2018/10/14. */public class MyAdapter extends ArrayAdapter { int resource; //构造方法传递三个参数,分别为:上下文,列表子布局和列表所需数据 public MyAdapter(Context context, int resource, List list){ //继承父类构造 super(context,resource,list); //后面会用到 this.resource = resource; } //加载适配器时会调用此方法 @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { //获得当前显示项的User对象 User user = getItem(position); ViewHolder holder; //若是第一次加载页面则调用此方法初始化 if(convertView == null){ convertView = LayoutInflater.from(getContext()).inflate(resource,parent,false); holder = new ViewHolder(); holder.tv_name = convertView.findViewById(R.id.item_name); holder.tv_phone = convertView.findViewById(R.id.item_phone); convertView.setTag(holder); }else{ holder = (ViewHolder) convertView.getTag(); } //将数据传递给控件并显示 holder.tv_name.setText(user.getName()); holder.tv_phone.setText(user.getPhone()); return convertView; } //缓存类,用于存放已存在的对象 class ViewHolder{ TextView tv_name; TextView tv_phone; }}
MainActivity:
import android.content.DialogInterface;import android.content.Intent;import android.net.Uri;import android.support.v7.app.AlertDialog;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.AdapterView;import android.widget.Button;import android.widget.ListView;import android.widget.TextView;import com.example.lenovo.work.adapter.MyAdapter;import com.example.lenovo.work.dbutil.UtilDao;import com.example.lenovo.work.entity.User;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity implements View.OnClickListener { private TextView textNum; private Button button; private ListView listView; private List list,newList; private UtilDao dao; private MyAdapter adapter; private int listNum = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化控件 initWidget(); //实例dao DbUtil(); //显示ListView showListView(); //显示listView的条目数量 linkmanNum(); } /** * 初始化控件 * */ private void initWidget(){ button = findViewById(R.id.main_but); listView = findViewById(R.id.main_list_view); textNum = findViewById(R.id.main_num); newList = new ArrayList<>(); list = new ArrayList<>(); } /** * 显示ListView * */ public void showListView(){ //查询数据 /** * 添加数据到链表中 * **/ list = dao.inquireData(); /** * 创建并绑定适配器 * */ adapter = new MyAdapter(this,R.layout.item,list); listView.setAdapter(adapter); /** * ListView事件监听 * */ listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { dialogList(); listNum = i; } }); button.setOnClickListener(this); } /** * 普通对话框 * */ public void dialogNormal(){ AlertDialog.Builder builder = new AlertDialog.Builder(this); DialogInterface.OnClickListener dialogOnClick = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { User userDel = list.get(listNum); switch (i){ case DialogInterface.BUTTON_POSITIVE: dao.delData("userName=?",new String[]{userDel.getName()}); refresh(); break; case DialogInterface.BUTTON_NEGATIVE: break; default:break; } } }; builder.setTitle("删除联系人"); builder.setMessage("确定要删除吗?"); builder.setPositiveButton("确定", dialogOnClick); builder.setNegativeButton("取消",dialogOnClick); builder.create().show(); } /** * 选项列表 * */ public void dialogList(){ final String[] items = {"拨打电话","发送短信","编辑","删除"}; AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setItems(items, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { dialogInterface.dismiss(); //拿到当前选中项的 User 对象 User userNum = list.get(listNum); Intent intent; switch (i){ //拨打电话 case 0: intent = new Intent(Intent.ACTION_DIAL); intent.setData(Uri.parse("tel:" + userNum.getPhone())); startActivity(intent); break; //发送短信 case 1: intent = new Intent(Intent.ACTION_SENDTO); intent.setData(Uri.parse("smsto:" + userNum.getPhone())); startActivity(intent); break; case 2: intent = new Intent(MainActivity.this,AddData.class); //传入当前选中项的姓名和电话以在编辑页面中显示在输入框中 intent.putExtra("edit_name",userNum.getName().toString()); intent.putExtra("edit_phone",userNum.getPhone().toString()); startActivityForResult(intent,2); break; //弹出对话框提示是否删除 case 3: dialogNormal(); break; default: break; } } }); builder.create().show(); } //刷新 public void refresh(){ //最后查询数据刷新列表 getNotifyData(); } //页面顶部显示ListView条目数 public void linkmanNum(){ textNum.setText("("+list.size()+")"); } //点击添加按钮 @Override public void onClick(View view) { switch (view.getId()){ case R.id.main_but: //跳转到 AddData Activity 传入请求码 1 Intent intent = new Intent(MainActivity.this,AddData.class); startActivityForResult(intent,1); break; default:break; } } public void DbUtil(){ dao = ((MyApplication)this.getApplication()).getDao(); } /** * 当页面回到此活动时,调用此方法,刷新ListView * */ @Override protected void onResume() { super.onResume(); getNotifyData(); } /** * 这个是用来动态刷新 * */ public void getNotifyData(){ //使用新的容器获得最新查询出来的数据 newList = dao.inquireData(); //清除原容器里的所有数据 list.clear(); //将新容器里的数据添加到原来容器里 list.addAll(newList); //更新页面顶部括号里显示数据 linkmanNum(); //刷新适配器 adapter.notifyDataSetChanged(); } /** * 上一个页面传回来的值 * */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode){ //请求码为1,表示点击了添加按钮 case 1: //执行添加方法 if(resultCode == RESULT_OK){ String[] key = data.getStringArrayExtra("key"); String[] values = data.getStringArrayExtra("values"); dao.addData("UserInfo",key,values); } break; //请求码为2,表示点击了编辑按钮 case 2: //执行修改方法 if(resultCode == RESULT_OK){ User user = list.get(listNum); String name = data.getStringExtra("name"); String phone = data.getStringExtra("phone"); String[] values = {name,phone,user.getName()}; dao.update(values); } break; } }}
添加修改页面,这两个功能都用的是一个Activity,通过请求码和结果码判断是哪个按钮触发了这个Activity从而实现对应功能业务。
<?xml version="1.0" encoding="utf-8"?>
import android.content.Intent;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;import android.widget.EditText;import com.example.lenovo.work.dbutil.UtilDao;/** * Created by lenovo on 2018/10/14. */public class AddData extends AppCompatActivity { private EditText edit_name,edit_phone; private Button but; private UtilDao dao; private Intent intent; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_adddata); //初始化组件 initWidget(); DbUtil(); /** * 点击编辑按钮传过来的值 * 用于显示当前编辑项的数据信息 * */ intent = getIntent(); String user_name = intent.getStringExtra("edit_name"); String user_phone = intent.getStringExtra("edit_phone"); edit_name.setText(user_name); edit_phone.setText(user_phone); but.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //获取到两个输入框的值 String name = edit_name.getText().toString(); String phone = edit_phone.getText().toString(); if(!name.equals("") && !phone.equals("")){ /** * 数据库操作需要用到的数据 * 详情请查看 UtilDao 类下的 addData() 方法 * */ String[] key = {"userName","userPhone"}; String[] values = {name,phone}; intent = new Intent(); //点击添加按钮则返回 key 和 values 数组 intent.putExtra("key",key); intent.putExtra("values",values); //点击编辑按钮则返回 name 和 phone 字符串 intent.putExtra("name",name); intent.putExtra("phone",phone); setResult(RESULT_OK,intent); finish(); } else if(name.equals("") || phone.equals("")){ finish(); } } }); } /** * 初始化控件 * */ private void initWidget(){ edit_name = findViewById(R.id.add_edit_name); edit_phone = findViewById(R.id.add_edit_phone); but = findViewById(R.id.add_but); } public void DbUtil(){ dao = ((MyApplication)this.getApplication()).getDao(); }}
OK!大功告成!
最后附上AndroidManifest.xml文件代码:
<?xml version="1.0" encoding="utf-8"?>
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
源码
更多相关文章
- Android 中LayoutInflater(布局加载器)源码篇之rInflate方法
- Android创建和使用数据库
- Android解析Intent Filter的方法
- android中访问本机服务器的方法
- Android中使用imageviewswitcher 实现图片切换轮播导航的方法
- Android NDK环境创建方法简介