Android App开发学习第8天:数据存储技术

SharedPreferences存储

什么是SharedPreferences存储?
它是Android提供的,用来以最简单的方式对数据进行永久保存的方法。

SharedPreferences存储的文件格式及路径
文件格式:XML文件
存储路径:data目录下找到对应的程序包名下找到shared_prefs目录里有mrsoft.xml文件用来作为存储文件。

使用SharedPreferences存储数据的步骤
1.获取SharedPreferences对象
1.getSharedPreferences()
getSharedPreferences(Stringname, int mode):mode分两个常量,MODE_PRIVATE和MODE_MULTI_PROCESS。
MODE_PRIVATE:被本应用读写
MODE_MULTI_PROCESS:跨应用读写

2.getPreferences()
getPreferences(int mode)
MODE_PRIVATE:被本应用读写
MODE_MULTI_PROCESS:跨应用读写

2.获得SharedPreferences.Editor对象
edit()
3.向SharedPreferences.Editor对象中添加数据
put+数据类型,如:putBoolean()、putString()、putInt()
4.提交数据
commit()

使用SharedPreferences读取数据的步骤
1.获取SharedPreferences对象
2.使用SharedPreferences类提供的getXxx()方法获取数据

模拟手机QQ自动登录的功能,实现使用SharedPreferences存储保存输入的账号和密码。
设置QQ登录界面


    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/username"
        android:hint="QQ号/手机号/邮箱"
        android:maxLines="1"
        android:layout_marginTop="220dp"/>
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:maxLines="1"
        android:id="@+id/password"
        android:hint="密码"
        />
    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/login"
        android:src="@drawable/login"
        android:layout_gravity="center"
        />

设置主界面

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/qq_main"
    tools:context=".MessageActivity">

实现自动登录和手动登录

public class MainActivity extends AppCompatActivity {
    private  String mr = "mr",mrsoft="mrsoft";//定义后台账号和密码
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final  EditText usernameET = this.findViewById(R.id.username); //获取账号编辑框
        final  EditText passwordET = this.findViewById(R.id.password);  //获取密码编辑框
        ImageButton login = this.findViewById(R.id.login);  //获取登录按钮
        //获取Shared Preferences对象
        final SharedPreferences sp =getSharedPreferences("mrsoft",MODE_PRIVATE);
//        实现自动登录功能
        String username = sp.getString("username",null);//获取账号信息
        String password = sp.getString("password",null);//获取密码
        if (username!=null &&password!=null){
            if (username.equals(mr) &&password.equals(mrsoft)){
                Intent intent = new Intent(MainActivity.this, MessageActivity.class);
                startActivity(intent);
            }
        }else {
//        实现手动登录并且存储账号和密码
            login.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    String in_username = usernameET.getText().toString();//获取输入的账号
                    String in_password = passwordET.getText().toString();//获取输入的密码
                    SharedPreferences.Editor editor = sp.edit(); //获取Editer对象
                    if (in_username.equals(mr) && in_password.equals(mrsoft)){
                        editor.putString("username",in_username); //保存账号
                        editor.putString("password",in_password); //保存密码
                        editor.commit();//提交信息
                        Intent intent = new Intent(MainActivity.this, MessageActivity.class);
                        startActivity(intent);
                        Toast.makeText(MainActivity.this,"已保存账号和密码",Toast.LENGTH_SHORT).show();
                    }else {
                        Toast.makeText(MainActivity.this,"账号或密码错误",Toast.LENGTH_SHORT).show();
                    }

                }
            });
        }

    }
}

文件存储

输入流:openFileInput()
输出流:openFileOutput()
内部存储
内部存储的文件路径:
在data目录下指定程序包名下的files目录的的文件都是内部存储文件
内部存储的特点:
1.默认只能被创建它的应用访问到
2.当这个而应用卸载后,内部存储中的文件也被删除
3.一旦内部存储空间耗尽,手机也就无法使用
写入文件
1.获取FileOutputStream对象
2.调用write()方法
3.调用flush()方法
4.调用close()方法
读取文件
1.获取FileInputStream对象
2.调用read()方法
3.调用close()方法
使用内部存储实现一个简易备忘录
定义一个备忘录

<!--  备忘录信息 -->
    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:layout_marginTop="50dp"
        android:gravity="top"/>
<!--  保存按钮  -->
    <ImageButton
        android:id="@+id/btn_save"
        android:layout_width="41dp"
        android:layout_height="30dp"
        android:scaleType="fitXY"
        android:layout_alignParentRight="true"
        android:src="@drawable/add"/>
    <!--  取消按钮  -->
    <ImageButton
        android:id="@+id/btn_cancel"
        android:layout_width="41dp"
        android:layout_height="30dp"
        android:scaleType="fitXY"
        android:layout_toLeftOf="@+id/btn_save"
        android:src="@drawable/cancel"/>

实现对备忘录的保存和自动读取

public class MainActivity extends AppCompatActivity {
    byte[] buffer = null;//定义保存数据的数组

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final EditText etext = this.findViewById(R.id.editText);
        ImageButton btn_save = this.findViewById(R.id.btn_save);
        ImageButton btn_cancel = this.findViewById(R.id.btn_cancel);

        btn_save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                保存填写的备忘信息
                FileOutputStream fos =null; //声明文件输出流
                String text = etext.getText().toString(); //获取输入的备忘信息
                try {
                    fos = openFileOutput("memo",MODE_PRIVATE);//获得文件输出流对象
                    fos.write(text.getBytes());//保存备忘信息
                    fos.flush();//清楚缓存
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }finally {
                    if (fos!=null){
                    try {
                        fos.close();//关闭输出流
                        Toast.makeText(MainActivity.this,"保存成功",Toast.LENGTH_SHORT).show();
                    } catch (IOException e) {
                        e.printStackTrace();
                        }
                    }
                }

            }
        });
//        读取保存的备忘信息
        FileInputStream fis =null;
        try {
            fis = openFileInput("memo");//获得文件输入流对象
            buffer = new byte[fis.available()];//实例化字节数组
            fis.read(buffer);//从输入流中读取数据
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (fis!=null){
                try {
                fis.close();//关闭输入流对象
                String data = new String(buffer);//把字节数组中的数据转换为字符串
                etext.setText(data);//显示读取的内容
            } catch (IOException e) {
                e.printStackTrace();
             }
            }
        }

        btn_cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();//退出应用
            }
        });
    }
}

外部存储
读、写外部存储空间上文件的步骤
获取外部存储目录
Environment.getExternalStorageDirectory()
读、写外部存储空间中的文件
FileInoutStream FileOutoutStream

使用外部存储实现一个简易的备忘录
定义一个备忘录

<!--  备忘录信息 -->
    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:layout_marginTop="50dp"
        android:gravity="top"/>
<!--  保存按钮  -->
    <ImageButton
        android:id="@+id/btn_save"
        android:layout_width="41dp"
        android:layout_height="30dp"
        android:scaleType="fitXY"
        android:layout_alignParentRight="true"
        android:src="@drawable/add"/>
    <!--  取消按钮  -->
    <ImageButton
        android:id="@+id/btn_cancel"
        android:layout_width="41dp"
        android:layout_height="30dp"
        android:scaleType="fitXY"
        android:layout_toLeftOf="@+id/btn_save"
        android:src="@drawable/cancel"/>

实现对备忘录的保存和自动读取


public class MainActivity extends AppCompatActivity {
    byte[] buffer = null;//定义保存数据的数组
    File file;//声明一个文件对象,用来指定外部村粗文件的

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final EditText etext = this.findViewById(R.id.editText);
        ImageButton btn_save = this.findViewById(R.id.btn_save);
        ImageButton btn_cancel = this.findViewById(R.id.btn_cancel);
        file = new File(Environment.getExternalStorageDirectory(),"Text.text");//实例化文件对象
        btn_save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                保存填写的备忘信息
                FileOutputStream fos =null; //声明文件输出流
                String text = etext.getText().toString(); //获取输入的备忘信息
                try {
                    fos = new FileOutputStream(file);//获得文件输出流对象
                    fos.write(text.getBytes());//保存备忘信息
                    fos.flush();//清除缓存
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }finally {
                    if (fos!=null){
                    try {
                        fos.close();//关闭输出流
                        Toast.makeText(MainActivity.this,"保存成功",Toast.LENGTH_SHORT).show();
                    } catch (IOException e) {
                        e.printStackTrace();
                        }
                    }
                }

            }
        });
//        读取保存的备忘信息
        FileInputStream fis =null;
        try {
            fis = new FileInputStream(file);//获得文件输入流对象
            buffer = new byte[fis.available()];//实例化字节数组
            fis.read(buffer);//从输入流中读取数据
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (fis!=null){
                try {
                fis.close();//关闭输入流对象
                String data = new String(buffer);//把字节数组中的数据转换为字符串
                etext.setText(data);//显示读取的内容
            } catch (IOException e) {
                e.printStackTrace();
             }
            }
        }

        btn_cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();//退出应用
            }
        });
    }
}

在AndroidManifest.xml文件中设置外部存储的读取权限

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

数据库存储

1.基本概念
1)SQLite是什么?为什么要用SQLite?SQLite有什么特点?
答:下面请听小猪娓娓道来:

①SQLite是一个轻量级的关系型数据库,运算速度快,占用资源少,很适合在移动设备上使用, 不仅支持标准SQL语法,还遵循ACID(数据库事务)原则,无需账号,使用起来非常方便!

②前面我们学习了使用文件与SharedPreference来保存数据,但是在很多情况下, 文件并不一定是有效的,如多线程并发访问是相关的;app要处理可能变化的复杂数据结构等等! 比如银行的存钱与取钱!使用前两者就会显得很无力或者繁琐,数据库的出现可以解决这种问题, 而Android又给我们提供了这样一个轻量级的SQLite,为何不用?

③SQLite支持五种数据类型:NULL,INTEGER,REAL(浮点数),TEXT(字符串文本)和BLOB(二进制对象) 虽然只有五种,但是对于varchar,char等其他数据类型都是可以保存的;因为SQLite有个最大的特点: 你可以各种数据类型的数据保存到任何字段中而不用关心字段声明的数据类型是什么,比如你 可以在Integer类型的字段中存放字符串,当然除了声明为主键INTEGER PRIMARY KEY的字段只能够存储64位整数! 另外, SQLite 在解析CREATE TABLE 语句时, 会忽略 CREATE TABLE 语句中跟在字段名后面的数据类型信息如下面语句会忽略 name字段的类型信息: CREATE TABLE person (personid integer primary key autoincrement, name varchar(20))

小结下特点:

SQlite通过文件来保存数据库,一个文件就是一个数据库,数据库中又包含多个表格,表格里又有 多条记录,每个记录由多个字段构成,每个字段有对应的值,每个值我们可以指定类型,也可以不指定 类型(主键除外)

PS:对了,Android内置的SQLite是SQLite 3版本的~

2)几个相关的类:
嘿嘿,学习一些新东西的时候,最不喜欢的莫过于遇到一些新名词,是吧,我们先来说下几个 我们在使用数据库时用到的三个类:

SQLiteOpenHelper:抽象类,我们通过继承该类,然后重写数据库创建以及更新的方法, 我们还可以通过该类的对象获得数据库实例,或者关闭数据库!

SQLiteDatabase:数据库访问类:我们可以通过该类的对象来对数据库做一些增删改查的操作

Cursor:游标,有点类似于JDBC里的resultset,结果集!可以简单理解为指向数据库中某 一个记录的指针!

2.使用SQLiteOpenHelper类创建数据库与版本管理
对于涉及数据库的app,我们不可能手动地去给他创建数据库文件,所以需要在第一次启用app 的时候就创建好数据库表;而当我们的应用进行升级需要修改数据库表的结构时,这个时候就需要 对数据库表进行更新了;对于这两个操作,安卓给我们提供了SQLiteOpenHelper的两个方法, onCreate( )与onUpgrade( )来实现

方法解析:

onCreate(database):首次使用软件时生成数据库表
onUpgrade(database,oldVersion,newVersion):在数据库的版本发生变化时会被调用, 一般在软件升级时才需改变版本号,而数据库的版本是由程序员控制的,假设数据库现在的 版本是1,由于业务的变更,修改了数据库表结构,这时候就需要升级软件,升级软件时希望 更新用户手机里的数据库表结构,为了实现这一目的,可以把原来的数据库版本设置为2 或者其他与旧版本号不同的数字即可!
代码示例:

public class MyDBOpenHelper extends SQLiteOpenHelper {
    public MyDBOpenHelper(Context context, String name, CursorFactory factory,
            int version) {super(context, "my.db", null, 1); }
    @Override
    //数据库第一次创建时被调用
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE person(personid INTEGER PRIMARY KEY AUTOINCREMENT,name VARCHAR(20))");
        
    }
    //软件版本号发生改变时调用
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("ALTER TABLE person ADD phone VARCHAR(12) NULL");
    }
}

代码解析:

上述代码第一次启动应用,我们会创建这个my.db的文件,并且会执行onCreate()里的方法, 创建一个Person的表,他又两个字段,主键personId和name字段;接着如我我们修改db的版本 号,那么下次启动就会调用onUpgrade()里的方法,往表中再插入一个字段!另外这里是插入 一个字段,所以数据不会丢失,如果是重建表的话,表中的数据会全部丢失,下一节我们会 来教大家如何解决这个问题!

流程小结:

Step 1:自定义一个类继承SQLiteOpenHelper类
Step 2:在该类的构造方法的super中设置好要创建的数据库名,版本号
Step 3:重写onCreate( )方法创建表结构
Step 4:重写onUpgrade( )方法定义版本号发生改变后执行的操作
3.如何查看我们生成的db文件
当我们调用上面的MyDBOpenhelper的对象的getWritableDatabase()就会在下述目录下创建我们的db 数据库文件:

在这里插入图片描述

我们发现数据库有两个,前者是我们创建的数据库,而后者则是为了能让数据库支持事务而产生的 临时的日志文件!一般的大小是0字节! 而在File Explorer里我们确是打不开文件的,连txt都打不开,何况是.db! 所以下面给大家两条路选:

1.先导出来,然后用SQLite的图形化工具查看
2.配置adb环境变量后,通过adb shell来查看(命令行,装比利器)!
嗯,接着给大家演示上述两种方法,选自己喜欢的一种就可以了~~

方法1:使用SQLite图形化工具查看db文件
这类软件有很多,笔者用的是SQLite Expert Professional,当然你也可以使用其他工具 又需要的可以下载:SQLiteExpert.zip

把我们的db文件导出到电脑桌面,打开SQLiteExpert,界面如下:

在这里插入图片描述

别问我怎么玩,导入db后自己慢慢玩,用法很简单,不懂百度~

至于方法二,本来是想试试的,后来发现sqlite命令找不到,试了几次就算了, 后面用到在细扣,有兴趣可以找下郭霖的《第一行代码——Android》按着流程图试试! 这里只贴前面的一部分,命令部分自己看书!

方法2:adb shell命令行带你装逼带你飞
1.配置SDK环境变量:

右键我的电脑 ——> 高级系统设置 -> 环境变量 -> 新建系统变量 -> 把SDK的platform-tools路径拷贝下: 比如笔者的:C:\Software\Coding\android-sdks-as\platform-tools
在这里插入图片描述

确定,然后再找到Path的环境变量,编辑,然后在结尾加上:%SDK_HOME%;
在这里插入图片描述

然后打开命令行,输入adb,唰唰唰一堆东西,就说明配置成功了!

——————重点——————: 在执行后续命令行指令之前,针对你的测试的机器可能有几种: 1.原生模拟器:那行,你跳过这里,继续往下 2.Genymotion模拟器:没戏,Genymotion Shell执行不了下述命令 3.真机(已root):那么你打开File Explorer看看data/data/目录下有东西没?没么? 下面提供一个方法,就是先装个RE文件管理器,然后授予RE Root权限,接着来到根目录: 然后长按data目录,会弹出这样的对话框:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

接着等他慢慢修改权限,修改完毕后,我们再次打开DDMS的File Explorer,我们可以看到:
在这里插入图片描述

好的,可以看到data/data里的东西了! ——————————————————————

2.进入adb shell,接着键入下述指令,来到我们app的databases目录下

在这里插入图片描述

接着依次输入下述指令:

sqlite3 my.db :打开数据库文件
.table 查看数据库中有哪些表 接着你直接输入数据库语句就可以了,比如查询:Select * from person
.schema:查看建表语句
.quit:退出数据库的编辑
.exit:退出设备控制台
…因为system/bin/sh sqlite3: not found,这个问题,后面Sqlite命令的都用不了, 要看效果图就自行查询郭大侠的书吧~而下面我们还是先导出db文件,然后用图形化的 数据库工具来查看!

4.使用Android提供的API操作SQLite
假如你没学过数据库相关的语法,或者你懒,不想写数据库语法,就可以使用Android给我们 提供的操作数据库的一些API方法,下面我们写个简单的例子来掩饰下这些API的用法!

代码示例:

运行效果图:
在这里插入图片描述

实现代码:

布局过于简单,就四个Button,就不贴了,直接贴MainActivity.java的代码:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Context mContext;
    private Button btn_insert;
    private Button btn_query;
    private Button btn_update;
    private Button btn_delete;
    private SQLiteDatabase db;
    private MyDBOpenHelper myDBHelper;
    private StringBuilder sb;
    private int i = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mContext = MainActivity.this;
        myDBHelper = new MyDBOpenHelper(mContext, "my.db", null, 1);
        bindViews();
    }

    private void bindViews() {
        btn_insert = (Button) findViewById(R.id.btn_insert);
        btn_query = (Button) findViewById(R.id.btn_query);
        btn_update = (Button) findViewById(R.id.btn_update);
        btn_delete = (Button) findViewById(R.id.btn_delete);

        btn_query.setOnClickListener(this);
        btn_insert.setOnClickListener(this);
        btn_update.setOnClickListener(this);
        btn_delete.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        db = myDBHelper.getWritableDatabase();
        switch (v.getId()) {
            case R.id.btn_insert:
                ContentValues values1 = new ContentValues();
                values1.put("name", "呵呵~" + i);
                i++;
                //参数依次是:表名,强行插入null值得数据列的列名,一行记录的数据
                db.insert("person", null, values1);
                Toast.makeText(mContext, "插入完毕~", Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_query:
                sb = new StringBuilder();
                //参数依次是:表名,列名,where约束条件,where中占位符提供具体的值,指定group by的列,进一步约束
                //指定查询结果的排序方式
                Cursor cursor = db.query("person", null, null, null, null, null, null);
                if (cursor.moveToFirst()) {
                    do {
                        int pid = cursor.getInt(cursor.getColumnIndex("personid"));
                        String name = cursor.getString(cursor.getColumnIndex("name"));
                        sb.append("id:" + pid + ":" + name + "\n");
                    } while (cursor.moveToNext());
                }
                cursor.close();
                Toast.makeText(mContext, sb.toString(), Toast.LENGTH_SHORT).show();
                break;
            case R.id.btn_update:
                ContentValues values2 = new ContentValues();
                values2.put("name", "嘻嘻~");
                //参数依次是表名,修改后的值,where条件,以及约束,如果不指定三四两个参数,会更改所有行
                db.update("person", values2, "name = ?", new String[]{"呵呵~2"});
                break;
            case R.id.btn_delete:
                //参数依次是表名,以及where条件与约束
                db.delete("person", "personid = ?", new String[]{"3"});
                break;
        }
    }
}

5.使用SQL语句操作数据库
当然,你可能已经学过SQL,会写相关的SQL语句,而且不想用Android提供的这些API, 你可以直接使用SQLiteDatabase给我们提供的相关方法:

execSQL(SQL,Object[]):使用带占位符的SQL语句,这个是执行修改数据库内容的sql语句用的
rawQuery(SQL,Object[]):使用带占位符的SQL查询操作 另外前面忘了介绍下Curosr这个东西以及相关属性,这里补充下: ——Cursor对象有点类似于JDBC中的ResultSet,结果集!使用差不多,提供一下方法移动查询结果的记录指针:
move(offset):指定向上或者向下移动的行数,整数表示向下移动;负数表示向上移动!
moveToFirst():指针移动到第一行,成功返回true,也说明有数据
moveToLast():指针移动到最后一样,成功返回true;
moveToNext():指针移动到下一行,成功返回true,表明还有元素!
moveToPrevious():移动到上一条记录
getCount( )获得总得数据条数
isFirst():是否为第一条记录
isLast():是否为最后一项
moveToPosition(int):移动到指定行
使用代码示例:

1.插入数据:

public void save(Person p)
{
    SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
    db.execSQL("INSERT INTO person(name,phone) values(?,?)",
                new String[]{p.getName(),p.getPhone()});
}

2.删除数据:

public void delete(Integer id)
{
    SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
    db.execSQL("DELETE FROM person WHERE personid = ?",
                new String[]{id});
}

3.修改数据:

public void update(Person p)
{
    SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
    db.execSQL("UPDATE person SET name = ?,phone = ? WHERE personid = ?",
        new String[]{p.getName(),p.getPhone(),p.getId()});
}

4.查询数据:

public Person find(Integer id)
{
    SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
    Cursor cursor =  db.rawQuery("SELECT * FROM person WHERE personid = ?",
            new String[]{id.toString()});
    //存在数据才返回true
    if(cursor.moveToFirst())
    {
        int personid = cursor.getInt(cursor.getColumnIndex("personid"));
        String name = cursor.getString(cursor.getColumnIndex("name"));
        String phone = cursor.getString(cursor.getColumnIndex("phone"));
        return new Person(personid,name,phone);
    }
    cursor.close();
    return null;
}

5.数据分页:

public List<Person> getScrollData(int offset,int maxResult)
{
    List<Person> person = new ArrayList<Person>();
    SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
    Cursor cursor =  db.rawQuery("SELECT * FROM person ORDER BY personid ASC LIMIT= ?,?",
        new String[]{String.valueOf(offset),String.valueOf(maxResult)});
    while(cursor.moveToNext())
    {
        int personid = cursor.getInt(cursor.getColumnIndex("personid"));
        String name = cursor.getString(cursor.getColumnIndex("name"));
        String phone = cursor.getString(cursor.getColumnIndex("phone"));
        person.add(new Person(personid,name,phone)) ;
    }
    cursor.close();
    return person;
}

6.查询记录数:

public long getCount()
{
    SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
    Cursor cursor =  db.rawQuery("SELECT COUNT (*) FROM person",null);
    cursor.moveToFirst();
    long result = cursor.getLong(0);
    cursor.close();
    return result;      
}   

PS:除了上面获取条数的方法外还可以使用cursor.getCount()方法获得数据的条数, 但是SQL语句要改改!比如SELECT * FROM person;

使用SQLit实现操作中英文词典数据库

定义布局界面
主界面Activity_main

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:layout_marginTop="20dp"
        android:text="语言自动检测"
       />
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <TextView
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="翻译"
                android:layout_marginTop="20dp"
                ></TextView>

            <ImageButton
                android:id="@+id/search_btn"
                android:layout_width="43dp"
                android:layout_height="19dp"
                android:layout_marginTop="20dp"
                android:scaleType="fitXY"
                android:src="@drawable/left" />

        </LinearLayout>
    </LinearLayout>
    <EditText
        android:id="@+id/search_et"
        android:layout_width="match_parent"
        android:layout_height="160dp"
        android:hint="在此输入要翻译的单词"
        android:scrollbars="vertical"
        android:maxLines="6"/>

    <ListView
        android:id="@+id/result_listView"
        android:layout_width="match_parent"
        android:layout_height="124dp" />
    <Button
        android:id="@+id/btn_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="添加生词"
        android:layout_marginLeft="200dp"/>


</LinearLayout>

添加界面activity_add

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".AddActivity">
    <EditText
        android:id="@+id/add_word"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="单词"
        android:maxLines="1"/>
    <EditText
        android:id="@+id/add_interpret"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="解释"
        android:maxLines="1"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/save_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="保存"
            />
        <Button
            android:id="@+id/cancel_btn1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="取消"
            />
    </LinearLayout>

</LinearLayout>

返回结果的样式界面result_main

<?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="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/result_word"/>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/result_interpret"/>


</LinearLayout>

定义一个类继承SQLiteOpenHelper类操作数据库

public class DBOpenHelper extends SQLiteOpenHelper {
    final String CREATE_TABLE_SQL = "create table tb_dict (_id integer primary key autoincrement , word,detail)";//定义创建数据库表的SQL语句

    public DBOpenHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, null, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_TABLE_SQL);//创建单词的数据表
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.i("词典", "--版本更新" + oldVersion + "-->" + newVersion);
    }
}

主Activity实现添加生词和翻译功能


public class MainActivity extends AppCompatActivity {
    private DBOpenHelper dbOpenHelper;//声明DBOpenHelper对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dbOpenHelper =     new DBOpenHelper(MainActivity.this, "db_dict", null, 1);//实例化DBOpenHelper对象,用来创建数据库


        final ListView listView = this.findViewById(R.id.result_listView);//获取显示结果的LsitView
        final EditText etSearch = this.findViewById(R.id.search_et);//获取查询内容的编辑区
        ImageButton btnSearch = this.findViewById(R.id.search_btn);//获取查询按钮
        Button btn_add = this.findViewById(R.id.btn_add);//获取跳转添加生词界面的按钮
        btn_add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, AddActivity.class);
                startActivity(intent);
            }
        });

        btnSearch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String key = etSearch.getText().toString();//获取要查询的单词
                Cursor cursor = dbOpenHelper.getReadableDatabase().query("tb_dict", null, "word=?", new String[]{key}, null, null, null);//执行查询操作
                ArrayList<Map<String, String>> resultList = new ArrayList<>();//创建ArrayList对象
                while (cursor.moveToNext()) {
                    Map<String, String> map = new HashMap<String, String>();
                    map.put("word", cursor.getString(1));
                    map.put("interpret", cursor.getString(2));
                    resultList.add(map);
                }
                if (resultList == null || resultList.size() == 0) {//如果数据库中没有数据
                    //显示提示信息,没有相关记录
                    Toast.makeText(MainActivity.this, "很遗憾,没有相关记录!", Toast.LENGTH_SHORT).show();

                } else {
                    //否则将查询的结果显示到ListView列表中
                    SimpleAdapter simpleAdapter = new SimpleAdapter(MainActivity.this, resultList
                            , R.layout.result_main
                            , new String[]{"word", "interpret"}, new int[]{
                            R.id.result_word, R.id.result_interpret
                    });
                    listView.setAdapter(simpleAdapter);
                }

            }
        });

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (dbOpenHelper!=null){
            dbOpenHelper.close();//关闭数据库连接
        }
    }
}

AddActivity实现添加生词


public class AddActivity extends AppCompatActivity {
    private DBOpenHelper dbOpenHelper;//声明DBOpenHelper对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add);
        dbOpenHelper=   new DBOpenHelper(AddActivity.this, "db_dict", null, 1);//实例化DBOpenHelper对象,用来创建数据库
        final EditText etWord = this.findViewById(R.id.add_word);//获取添加单词的编辑框
        final EditText etInterpret = this.findViewById(R.id.add_interpret);//获取添加解释的编辑框
        Button btn_Save = this.findViewById(R.id.save_btn); //获取保存按钮
        Button btn_Cancel = this.findViewById(R.id.cancel_btn1); //获取取消按钮

        btn_Save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String word = etWord.getText().toString();//获取填写的生词
                String interpret = etInterpret.getText().toString();//获取填写的解释
                if (word.equals("") || interpret.equals("")) {//如果填写的单词或者解释为空时
                    Toast.makeText(AddActivity.this, "填写的单词或解释为空", Toast.LENGTH_SHORT).show();
                } else {
                    insertData(dbOpenHelper.getReadableDatabase(), word, interpret);//插入生词
                    Toast.makeText(AddActivity.this, "添加生词成功", Toast.LENGTH_SHORT).show();
                }

            }
        });
        btn_Cancel.setOnClickListener(new View.OnClickListener() {//实现返回查询单词界面
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(AddActivity.this, MainActivity.class);
                startActivity(intent);
            }
        });
    }

    //插入数据的方法
    private void insertData(SQLiteDatabase sqLiteDatabase, String word, String interpret) {
        ContentValues values = new ContentValues();
        values.put("word", word);//保存单词
        values.put("detail", interpret);//保存解释
        sqLiteDatabase.insert("tb_dict", null, values);//执行插入操作
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (dbOpenHelper != null) {
            dbOpenHelper.close();//关闭数据库连接
        }
    }
}

数据共享

Content Provider
数据模型
Content Provider使用基于数据模型的简单表格来提供其中的数据
URI
content://com.mingrisoft.employeeprovider/person/001

创建和使用Content Provider的步骤
继承ContentProvider类
声明ContentProvider,AndroidManifest.xml 《provider》
使用ContentProvider:添加insert(),查询query(),删除delete(),更新update()

模拟微信电话本通过Content Provider读取所有联系人

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@drawable/bg2"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="联系人"
        android:textColor="#646400"
        android:textSize="50sp"
         />

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

package com.example;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ContentResolver;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    private String colums = ContactsContract.Contacts.DISPLAY_NAME;//希望获得姓名

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView tv = findViewById(R.id.result);
        tv.setText(getQueryData());
    }
    private  CharSequence getQueryData(){
        StringBuilder stringBuilder = new StringBuilder();//用于保存获取的联系人
        ContentResolver resolver = getContentResolver();
        Cursor cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI,null,null,null,null);//查询记录
        int displayNameIndex = cursor.getColumnIndex(colums);//获得姓名记录的索引值
        for (cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()){
            String displayName = cursor.getString(displayNameIndex);
            stringBuilder.append(displayName+"\n");
        }
        cursor.close();//关闭记录集
        return stringBuilder.toString();//返回查询结果
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值