一、整体实现步骤
1. 新建布局文件
2. 建立实体类
3. 建立MySqliteOpenHelpter来帮助我们管理数据库
4. 建立数据库适配器,执行具体的CURD操作
5. 建立内容提供者
6. 在第二个应用中调用第一个应用中的内容(这里没有提到权限的事情)
1.新建布局文件
-
效果
布局代码:
2.在Activity中先把事件给写上回头再写全
- 代码
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.privder_main);
}
//增加数据
public void insert(View v){
}
//修改一条数据
public void update(View v){
}
//删除一条数据
public void delete(View v){
}
//查询单个
public void find(View v){
}
//查询所有
public void findAll(View v){
}
//创建数据表
public void createTable(View v){
}
//删除数据表
public void dropTable(View v){
}
}
3. 建立一个员工实体类
public class Emp {
//id号
private int id;
//员工姓名
private String name;
//员工年龄
private int age;
public Emp() {}
public Emp(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Emp{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
员工实体类讲解
- 我这里主要包含三个属性(可以自由发挥)
- 员工编号
- 员工姓名
- 员工年龄
- 实体类可以自己定义,只要符合业务需求即可
4. MySQLiteOpenHelper(名字有点Low~ haha~)
- 代码
public class MyDatabaseHelper extends SQLiteOpenHelper {
//定义数据表
public static final String TAB_NAME ="emp.db";
//定义列
public static final String NAME = "name";
public static final String AGE = "age";
//定义建表语句
public static final String CREATE_EMP="CREATE TABLE emp(" +
"id PRIMARY KEY AUTOINCREMENT," +
"name VARCHAR(20) NOT NULL," +
"age INT)";
//定义数据库版本
public static final int version = 1;
public MyDatabaseHelper(Context context) {
super(context, TAB_NAME, null, version, null);
}
//当没有表的时候执行此方法
@Override
public void onCreate(SQLiteDatabase db) {
//写入建表语句
db.execSQL(CREATE_EMP);
}
//当数据库版本不对的时候调用此方法。
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
SQLiteOpenHelper 管理数据库创建和版本管理的辅助类.。
- SQLiteOpenHelper 是一个抽象类,想要使用它的话,就需要创建一个自己的帮助类去继承它。并复写两个抽象方法
1.1 onCreate():创建时执行,已经存在不执行。
1.2 **onUpgrade()**:版本号不同时执行
- 两个重要的实例方法
2.1 **getReadableDatabase() **
2.2 **getWritableDatabase()**。
* 这两个方法都可以**创建或打开**一个现有的数据库(如果数据库已存在则直接打开,否则创建一个新的数据库)。
* 并返回一个可对数据库进行读写操作的对象。
* 不同处。当数据库不可写入时(如磁盘空间已满)getReadableDatabase() 方法返回的对象将以只读的方式去打开数据库,而 getWritableDatabase() 方法则将出现异常。
- 创建数据库的步骤
构建出** SQLiteOpenHelper 实例。
再调用它的 getReadableDatabase() 或 getWritableDatabase() **方法就能够创建数据库了。
数据库文件会存放在 **/data/data//databases/ 目录下。
此时,重写的 onCreate() **方法也会得到执行
- 官方文档:SQLiteOpenHelper
5.定义数据适配器
1.代码:
public class DatabaseAdapter {
//持有一个帮助类
MyDatabaseHelper helper;
public DatabaseAdapter(Context context) {
helper = new MyDatabaseHelper(context);
}
//具体的添加操作
public void insert(Emp emp){
//获取写数据库的权限
SQLiteDatabase db =helper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(MyDatabaseHelper.NAME,emp.getName());
values.put(MyDatabaseHelper.AGE,emp.getAge());
//插入操作
db.insert(MyDatabaseHelper.TAB_NAME,null,values);
}
//具体的修改操作
public void update(Emp emp){
//获取写数据的权限
SQLiteDatabase db = helper.getWritableDatabase();
//修改的条件
String whereClause = "id=?";
//修改的条件参数
String[] whereArgs = new String[]{"1"};
//修改的内容
ContentValues values = new ContentValues();
values.put(MyDatabaseHelper.ID,emp.getId());
values.put(MyDatabaseHelper.NAME,emp.getName());
values.put(MyDatabaseHelper.AGE,emp.getAge());
//修改操作
db.update(MyDatabaseHelper.TAB_NAME,values,whereClause,whereArgs);
}
//具体的删除操作
public void delete(int id){
//获取写数据的权限
SQLiteDatabase db = helper.getWritableDatabase();
String whereClause = "id=?";
String[] whereArgs = new String[]{String.valueOf(id)};
db.delete(MyDatabaseHelper.TAB_NAME,whereClause,whereArgs);
}
//具体的查询单个操作
public Emp find(int id){
//创建实体类对象
Emp emp = null;
//获取查询数据的权限
SQLiteDatabase db = helper.getReadableDatabase();
String[] columns = new String[]{MyDatabaseHelper.ID,MyDatabaseHelper.NAME,MyDatabaseHelper.AGE};
String selection = "id=?";
String[] selectionArgs = new String[]{String.valueOf(id)};
Cursor result = db.query(MyDatabaseHelper.TAB_NAME,columns,selection,selectionArgs,null,null,null);
//循环取值
if (result.moveToFirst()){
emp = new Emp();
emp.setId(result.getInt(0));
emp.setName(result.getString(1));
emp.setAge(result.getInt(2));
}
result.close();
return emp;
}
//具体的查询所有操作
public List findAll(){
//创建list集合
List list = new ArrayList<>();
//获取读取数据库的权限
SQLiteDatabase db = helper.getReadableDatabase();
String[] columns = new String[]{MyDatabaseHelper.ID,MyDatabaseHelper.NAME,MyDatabaseHelper.AGE};
Cursor res = db.query(MyDatabaseHelper.TAB_NAME,columns,"",new String[]{},null,null,null);
while (res.moveToNext()){
Emp emp = new Emp();
emp.setId(res.getInt(0));
emp.setName(res.getString(1));
emp.setAge(res.getInt(2));
list.add(emp);
}
res.close();
return list;
}
//具体的删表操作
public void dropTable(){
//获取写数据的权限
SQLiteDatabase db = helper.getWritableDatabase();
db.execSQL(MyDatabaseHelper.DROP_EMP);
}
//具体的建表操作
public void createTable(){
//获取写数据的权限
SQLiteDatabase db = helper.getWritableDatabase();
db.execSQL(MyDatabaseHelper.CREATE_EMP);
}
}
讲解
此适配器主要是帮我们具体的实现具体的业务操作而写的,我这里只是练习,未来你需要根据具体的业务去实现
最后完成这样的效果
开始写内容提供者
/**
* 内容提供者练习
*/
public class MyContentProvider extends ContentProvider {
//定义一个URI匹配器
public static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
//定义常量
public static final int INSERT = 1;
public static final int DELETE = 2;
public static final int UPDATE = 3;
public static final int QUERYBYID = 4;
public static final int QUERY = 5;
//持有引用
MyDatabaseHelper helper;
static {
//匹配的内容: content://cn.jewei.provider.emp/insert
matcher.addURI("cn.jewei.provider.emp","insert",INSERT);
//匹配的内容: content://cn.jewei.provider.emp/delete
matcher.addURI("cn.jewei.provider.emp","delete",DELETE);
//匹配的内容: content://cn.jewei.provider.emp/update
matcher.addURI("cn.jewei.provider.emp","update",UPDATE);
//匹配的内容: content://cn.jewei.provider.emp/query/5后面是数字的这种
matcher.addURI("cn.jewei.provider.emp","query/#",QUERYBYID);
//匹配的内容: content://cn.jewei.provider.emp/query
matcher.addURI("cn.jewei.provider.emp","query",QUERY);
}
public MyContentProvider() {
}
//启动的时候就会执行
@Override
public boolean onCreate() {
//初始化帮助类
helper = new MyDatabaseHelper(getContext());
return true;
}
//增加数据的操作
@Override
public Uri insert(Uri uri, ContentValues values) {
//首先匹配URI
if (matcher.match(uri) == INSERT){//匹配上就返回INSERT的值
SQLiteDatabase db = helper.getWritableDatabase();
//执行插入操作
db.insertOrThrow(MyDatabaseHelper.TAB_NAME,null,values);
}
return uri;
}
//删除操作
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
if (matcher.match(uri) == DELETE){
SQLiteDatabase db = helper.getWritableDatabase();
db.delete(MyDatabaseHelper.TAB_NAME,selection,selectionArgs);
}
return 0;
}
//更新操作
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
if (matcher.match(uri) == UPDATE){
SQLiteDatabase db = helper.getWritableDatabase();
db.update(MyDatabaseHelper.TAB_NAME,values,selection,selectionArgs);
}
return 0;
}
//查询操作
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
if (matcher.match(uri) == QUERYBYID){//查询单个操作
long id = ContentUris.parseId(uri);
SQLiteDatabase db = helper.getReadableDatabase();
return db.query(MyDatabaseHelper.TAB_NAME,projection,"id=?",new String[]{id+""},null,null,null);
}else if(matcher.match(uri) == QUERY){//查询所有
SQLiteDatabase db = helper.getReadableDatabase();
return db.query(MyDatabaseHelper.TAB_NAME,projection,null,null,null,null,null);
}
return null;
}
//主要用于查询是返回单个还是多个
@Override
public String getType(Uri uri) {
if (matcher.match(uri) == QUERYBYID){//查询单个操作
Log.i("privder","查询单个");
return "vnd.android.cursor.item/emp";
}else if(matcher.match(uri) == QUERY){//查询所有
Log.i("privder","查询一组");
return "vnd.android.cursor.dir/";
}
return "";
}
}
知识点:
- Uri(统一资源表示符)
适合不监测网络连接的通信机制
- 建立内容提供者的目的是提供一种安全的访问形式,就如同防火墙一样,允许可以访问的内容,拒绝一切非法的访问,我们学习内容提供者的目的试了以后能更好的使用系统提供给我们的信息,如果未来你做的应用特别大的时候,里面得数据足够提供一种服务的时候,这个时候内容提供者对你就特别的重要了。
编写另一个应用,模拟查询上一个应用的数据,完成内容提供者的整个流程
- 废话不多说,布局和上面的一样,这里不再写出
1.1 一张截图:
- 我们开始写Activity的内容接收具体代码
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//增加数据
public void insert(View v){
//创建一个内容接收者
ContentResolver resolver = getContentResolver();
ContentValues values = new ContentValues();
values.put("name","张无忌");
values.put("age",18);
Uri uri = Uri.parse("content://cn.jewei.provider.emp/insert");
resolver.insert(uri,values);
}
//修改数据
public void update(View v){
//创建一个内容接收者
ContentResolver resolver = getContentResolver();
//创建一个ContentValues用于存储数据
ContentValues values = new ContentValues();
values.put("id",1);
values.put("name","谢逊");
values.put("age",84);
Uri uri = Uri.parse("content://cn.jewei.provider.emp/update");
resolver.update(uri,values,"id=?",new String[]{"1"});
}
//删除数据
public void delete(View v){
//创建一个内容接收者
ContentResolver resolver = getContentResolver();
//创建uri
Uri uri = Uri.parse("content://cn.jewei.provider.emp/delete");
resolver.delete(uri,"id=?",new String[]{"1"});
}
//查询单个数据
public void find(View v){
//创建一个内容接收者
ContentResolver resolver = getContentResolver();
//创建uri
Uri uri = Uri.parse("content://cn.jewei.provider.emp/query/2");
//定义列
String[] column = new String[]{"id","name","age"};
Cursor res = resolver.query(uri,column,"id=?",new String[]{"2"},null);
Emp emp =null;
if (res.moveToNext()){
emp = new Emp();
emp.setId(res.getInt(0));
emp.setName(res.getString(1));
emp.setAge(res.getInt(2));
}
Toast.makeText(this,emp.toString(), Toast.LENGTH_SHORT).show();
}
//查询所有
public void findAll(View v){
//装在的容器
List list=new ArrayList<>();
//创建一个内容接收者
ContentResolver resolver = getContentResolver();
//创建uri
Uri uri = Uri.parse("content://cn.jewei.provider.emp/query");
//定义列
String[] column = new String[]{"id","name","age"};
Cursor res = resolver.query(uri,column,null,null,null);
Emp emp =null;
while (res.moveToNext()){
emp = new Emp();
emp.setId(res.getInt(0));
emp.setName(res.getString(1));
emp.setAge(res.getInt(2));
list.add(emp);
}
Toast.makeText(this, Arrays.toString(list.toArray()), Toast.LENGTH_SHORT).show();
}}
效果图
总结:
掌握好内容提供者的编写,能够更加的了解内部的机制,有助于我们更好地调用其他应用的数据,我这里没有设定任何的权限,正常来讲,我们可以自定义权限的,这时候调用者访问我们的应用中的数据就必须携带权限才可以,和系统的权限一样,没有权限你看不到,哈哈哈~