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<User> inquireData(){
        List<User> 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<User> inquireData(){
        List<User> 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里<application>标签里添加name属性,这点很重要!!!不然程序崩溃。

android:name=".MyApplication"

布局很简单,这里我就不过多的解释,自行理解:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context="com.example.lenovo.work.MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/main_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="联系人"
            android:textSize="20sp"
            android:layout_centerHorizontal="true"
            android:layout_alignBaseline="@id/main_but"/>

        <TextView
            android:id="@+id/main_num"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="(0)"
            android:layout_toRightOf="@id/main_text"
            android:layout_alignBaseline="@id/main_text"/>

        <Button
            android:id="@+id/main_but"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:text="添加"/>

    </RelativeLayout>

    <ListView
        android:id="@+id/main_list_view"
        android:layout_below="@id/main_but"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"></ListView>

</LinearLayout>

我们先建一个实体类,用于存储用户信息,作为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"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_margin="10dp">

        <TextView
            android:id="@+id/item_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="张三"
            android:textSize="18sp"
            android:textColor="#000000"/>

        <TextView
            android:id="@+id/item_phone"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="15234569876"/>

    </LinearLayout>

</LinearLayout>

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<User> {
    int resource;
    //构造方法传递三个参数,分别为:上下文,列表子布局和列表所需数据
    public MyAdapter(Context context, int resource, List<User> 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<User> 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"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp">

    <EditText
        android:id="@+id/add_edit_name"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:hint="姓名"/>

    <EditText
        android:id="@+id/add_edit_phone"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:hint="电话"
        android:layout_below="@id/add_edit_name"/>

    <Button
        android:id="@+id/add_but"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="确定"
        android:layout_below="@id/add_edit_phone"
        android:layout_alignParentRight="true"/>

</RelativeLayout>
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"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.lenovo.work" >

    <uses-permission android:name="android.permission.CALL_PHONE"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/txl"
        android:label="@string/app_name"
        android:roundIcon="@drawable/txl"
        android:supportsRtl="true"
        android:name=".MyApplication"
        android:theme="@style/AppTheme" >
        <activity android:name=".MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".AddData"/>
    </application>

</manifest>

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

源码

  • 54
    点赞
  • 314
    收藏
    觉得还不错? 一键收藏
  • 67
    评论
评论 67
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值