注意:在ContentProvider里面写对数据库增删改查的时候,千万不能 db.close();  cursor.close(); 等操作,不然其他应用访问不到数据,也没有必要写isOpen();

ContentProviderServer应用-->定义 MySqliteOpenHeper 数据库帮助操作类(创建数据库,创建表,初始化数据)

package liudeli.cp.server.cp;

import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; public class MySqliteOpenHeper extends SQLiteOpenHelper { private static final String DB_NAME = "dogDatabase.db";
private static final int VERSON = 1; /**
* 定义单例模式 懒汉式
*/
private static MySqliteOpenHeper mySqliteOpenHeper; public static MySqliteOpenHeper getInstance(Context context) {
if (null == mySqliteOpenHeper) {
synchronized (MySqliteOpenHeper.class) {
if (null == mySqliteOpenHeper) {
mySqliteOpenHeper = new MySqliteOpenHeper(context, DB_NAME, null,VERSON);
}
}
}
return mySqliteOpenHeper;
} private MySqliteOpenHeper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
} @Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table dog(_id integer primary key autoincrement, name text, age integer);");
initDogTableData(db);
} private void initDogTableData(SQLiteDatabase db) {
ContentValues contentValues = new ContentValues(); contentValues.put("name", "李光四");
contentValues.put("age", 88);
db.insert("dog", null, contentValues); contentValues.put("name", "李俊泽");
contentValues.put("age", 22);
db.insert("dog", null, contentValues); contentValues.put("name", "李狗");
contentValues.put("age", 23);
db.insert("dog", null, contentValues);
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }
}

ContentProviderServer应用-->定义 MyContentProvider 对数据库增删改查操作

package liudeli.cp.server.cp;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.util.Log; public class MyContentProvider extends ContentProvider { private final String TAG = MyContentProvider.class.getSimpleName(); /**
* 初始化数据库错误的示范: (不仅仅是在ContentProvider不能这样,在其他的组件也不能这样)
* MySqliteOpenHeper.getInstance(getContext()); 还没有执行 onCreate 是没有getContext的,会报错
* MySqliteOpenHeper.getInstance(this); 还没有执行 onCreate初始化 是没有getContext的,会报错
*/
// private MySqliteOpenHeper mySqliteOpenHeper = MySqliteOpenHeper.getInstance(getContext()); private MySqliteOpenHeper mySqliteOpenHeper; /**
* 只要在AndroidManifest.xml中配置了provider组件
* 应用打开后,会自动启动此方法
* @return
*/
@Override
public boolean onCreate() {
Log.d(TAG, "onCreate()");
mySqliteOpenHeper = MySqliteOpenHeper.getInstance(getContext());
return false;
} /**
* 查询
* @param uri 其他应用传递过来的Uri
* @param projection 其他应用传递过来的查询列
* @param selection 其他应用传递过来的查询条件
* @param selectionArgs 其他应用传递过来的查询条件参数值
* @param sortOrder 其他应用传递过来的排序
* @return
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Log.d(TAG, "查询到了数据....");
SQLiteDatabase db = mySqliteOpenHeper.getReadableDatabase(); /**
* 查询全部
*/
Cursor curosr = db.query("dog", // 表名
projection, // 查询的列
null, // selection 查询的条件 xxx=?
null, // selectionArgs 查询条件的值
null, // groupBy 分组
null, // having 分组过滤条件
null); // orderBy 排序 /**
* 在内容提供者里面,千万不能关闭数据库,关闭游标
*/ return curosr;
} /**
* 增加
* @param uri 其他应用传递过来的Uri
* @param values 其他应用传递过来的ContentValues
* @return
*/
@Override
public Uri insert(Uri uri, ContentValues values) {
Log.d(TAG, "插入了数据....");
SQLiteDatabase database = mySqliteOpenHeper.getWritableDatabase();
// 参数一:表名 参数二:其他应用传递过来的ContentValues
database.insert("dog", null, values); /**
* 在内容提供者里面,千万不能关闭数据库,关闭游标
*/
return null;
} /**
* 修改
* @param uri 其他应用传递过来的Uri
* @param values 其他应用传递过来的ContentValues
* @param selection 其他应用传递过来的查询条件
* @param selectionArgs 其他应用传递过来的查询条件参数值
* @return
*/
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
Log.d(TAG, "修改了数据....");
SQLiteDatabase database = mySqliteOpenHeper.getWritableDatabase();
// 参数一:表名 参数二:其他应用传递过来的ContentValues 参数三:其他应用传递过来的查询条件
database.update("dog", values, selection, selectionArgs); /**
* 在内容提供者里面,千万不能关闭数据库,关闭游标
*/
return 0;
} /**
* 删除
* @param uri 其他应用传递过来的Uri
* @param selection 其他应用传递过来的查询条件
* @param selectionArgs 其他应用传递过来的查询条件参数值
* @return
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
Log.d(TAG, "删除了数据....");
SQLiteDatabase database = mySqliteOpenHeper.getWritableDatabase();
// 参数一:表名 参数二:其他应用传递过来的查询条件 参数三:其他应用传递过来的查询条件的值
database.delete("dog", selection, selectionArgs); /**
* 在内容提供者里面,千万不能关闭数据库,关闭游标
*/
return 0;
} /**
* 得到类型 在后续的博客中会有讲解到
* @param uri
* @return
*/
@Override
public String getType(Uri uri) {
return null;
}
}

ContentProviderServer应用-->定义 在AndroidManifest.xml 中 对外暴露 MyContentProvider

    <!--
ContentProvider是组件需要配置
可以把ContentProvider看作是服务器
authorities 看作是服务器 服务器有访问的链接,authorities(授权) ,是唯一标识
android:enabled="true" 可以被系统实例化
android:exported="true" 允许对外输出
-->
<provider
android:authorities="autho.prov.cp.MyContentProvider"
android:name=".cp.MyContentProvider"
android:enabled="true"
android:exported="true"
/>

然后运行 ContentProviderServer应用:由于在AndroidManifest.xml中配置了MyContentProvider组件,只要运行 ContentProviderServer应用,就会自动初始化onCreate()方法

12-14 09:22:55.187 2013-2013/liudeli.cp.server D/MyContentProvider: onCreate()


ContentProviderClient应用 --> MainActivity中调用 ContentProviderServer应用的内容提供者

package liudeli.cp.client;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast; public class MainActivity extends AppCompatActivity { private EditText etID;
private ContentResolver contentResolver;
private ListView listview; private Uri uri;
private Cursor cursor; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); etID = findViewById(R.id.et_id);
contentResolver = getContentResolver();
listview = findViewById(R.id.listview); uri = Uri.parse("content://autho.prov.cp.MyContentProvider");
} public void test(View view) {
/**
* 可以想象客户端访问服务器,需要需要用到协议HTTP
* 而想访问ContentProvider,需要ContentResolver
*/
ContentResolver contentProvider = getContentResolver(); /**
* 可以想象访问服务器,需要这样拼接访问地址 http://
* 而想访问ContentProvider,需要这样拼接访问地址 content://
* 必须拿到暴露的授权authorities="autho.prov.cp.MyContentProvider" 进行拼接
*/
Uri uri = Uri.parse("content://autho.prov.cp.MyContentProvider"); // 查询
contentProvider.query(uri, null, null, null, null, null); // 增加
// contentProvider.insert(uri, null); // 修改
// contentProvider.update(uri, null, null, null); // 删除
// contentProvider.delete(uri, null, null);
} /**
* 查询
*/
public void query(View view) {
cursor = contentResolver.query(uri,
new String[]{"_id", "name", "age"},
null, null
, null, null); /**
* 使用SimpleCursorAdapter 适配器
*/
SimpleCursorAdapter simpleCursorAdapter = new
SimpleCursorAdapter(MainActivity.this, // 上下文
R.layout.layout_item, // Item布局
cursor, // Cursor 查询出来的游标 这里面有数据库里面的数据
new String[]{"_id", "name", "age"}, // 从哪里来,指的是 查询出数据库列名
new int[]{R.id.tv_id, R.id.tv_name, R.id.tv_age}, // 到哪里去,指的是,把查询出来的数据,赋值给Item布局 的控件
SimpleCursorAdapter.NO_SELECTION); // 给ListView设置使用SimpleCursorAdapter适配器
listview.setAdapter(simpleCursorAdapter); // 注意:在数据展示完成后,不要关闭游标, 在Activity结束后在关闭cursor.close();
} /**
* 增加
*/
public void insert(View view) {
if (TextUtils.isEmpty(etID.getText().toString())) {
Toast.makeText(MainActivity.this, "请输入ID", Toast.LENGTH_LONG).show();
return;
}
ContentValues vs = new ContentValues();
vs.put("name", "刘新龙" + etID.getText().toString());
vs.put("age", 90);
contentResolver.insert(uri, vs); // 规范写法应该是:simpleCursorAdapter.notifyDataSetChanged();
// 我这里为了测试下,就直接这样掉算了
query(null);
} /**
* 修改
*
* @param view
*/
public void update(View view) {
if (TextUtils.isEmpty(etID.getText().toString())) {
Toast.makeText(MainActivity.this, "请输入ID", Toast.LENGTH_LONG).show();
return;
}
ContentValues vs = new ContentValues();
vs.put("name", "王二麻子" + etID.getText().toString());
vs.put("age", 78);
contentResolver.update(uri, vs, "_id = ?", new String[]{etID.getText().toString()}); // 规范写法应该是:simpleCursorAdapter.notifyDataSetChanged();
// 我这里为了测试下,就直接这样掉算了
query(null);
} /**
* 删除
*
* @param view
*/
public void delete(View view) {
if (TextUtils.isEmpty(etID.getText().toString())) {
Toast.makeText(MainActivity.this, "请输入ID", Toast.LENGTH_LONG).show();
return;
} contentResolver.delete(uri, "_id = ?", new String[]{etID.getText().toString()}); // 规范写法应该是:simpleCursorAdapter.notifyDataSetChanged();
// 我这里为了测试下,就直接这样掉算了
query(null);
} /**
* 在Activity结束后在关闭cursor.close();
*/
@Override
protected void onDestroy() {
super.onDestroy();
if (cursor != null) {
cursor.close();
}
}
}

ContentProviderClient应用 --> 布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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"
tools:context=".MainActivity"> <LinearLayout
android:id="@+id/ll_buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="test"
android:onClick="test"
android:layout_weight="1"
/> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="查询"
android:layout_weight="1"
android:onClick="query"
/> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="增加"
android:layout_weight="1"
android:onClick="insert"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="修改"
android:layout_weight="1"
android:onClick="update"
/> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="删除"
android:layout_weight="1"
android:onClick="delete"
/> </LinearLayout> <LinearLayout
android:id="@+id/ll_et_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/ll_buttons"
android:layout_marginTop="10dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请输入_id号"
android:textSize="20sp"
/> <EditText
android:id="@+id/et_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/white"
android:layout_marginLeft="10dp"
/> </LinearLayout> <ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/ll_et_id"
android:layout_marginTop="20dp"></ListView> </RelativeLayout>

ContentProviderClient应用 --> 布局文件 -->ListView--> Item布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"> <TextView
android:id="@+id/tv_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="id"
android:textColor="@android:color/black"
/> <TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="name"
android:textColor="@android:color/black"
android:layout_marginTop="5dp"
/> <TextView
android:id="@+id/tv_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="age"
android:textColor="@android:color/black"
android:layout_marginTop="5dp"
/> </LinearLayout>

ContentProviderClient应用  操作 --->  ContentProviderServer应用的数据库

Android-ContentProvider简单的增删改查的更多相关文章

  1. salesforce 零基础学习(五十一)使用 Salesforce.com SOAP API 实现用户登录以及简单的增删改查(JAVA访问salesforce)

    此篇请参看:https://resources.docs.salesforce.com/202/latest/en-us/sfdc/pdf/salesforce_developer_environme ...

  2. MyBatis学习--简单的增删改查

    jdbc程序 在学习MyBatis的时候先简单了解下JDBC编程的方式,我们以一个简单的查询为例,使用JDBC编程,如下: Public static void main(String[] args) ...

  3. 通过JDBC进行简单的增删改查

    通过JDBC进行简单的增删改查(以MySQL为例) 目录 前言:什么是JDBC 一.准备工作(一):MySQL安装配置和基础学习 二.准备工作(二):下载数据库对应的jar包并导入 三.JDBC基本操 ...

  4. MyBatis简单的增删改查以及简单的分页查询实现

    MyBatis简单的增删改查以及简单的分页查询实现 <? xml version="1.0" encoding="UTF-8"? > <!DO ...

  5. 初试KONCKOUT+WEBAPI简单实现增删改查

    初试KONCKOUT+WEBAPI简单实现增删改查 前言 konckout.js本人也是刚刚接触,也是初学,本文的目的是使用ko和asp.net mvc4 webapi来实现一个简单增删改查操作.Kn ...

  6. MVC3.0+knockout.js+Ajax 实现简单的增删改查

    MVC3.0+knockout.js+Ajax 实现简单的增删改查 自从到北京入职以来就再也没有接触MVC,很多都已经淡忘了,最近一直在看knockout.js 和webAPI,本来打算采用MVC+k ...

  7. SpringMVC之简单的增删改查示例(SSM整合)

    本篇文章主要介绍了SpringMVC之简单的增删改查示例(SSM整合),这个例子是基于SpringMVC+Spring+Mybatis实现的.有兴趣的可以了解一下. 虽然已经在做关于SpringMVC ...

  8. python3.6 使用 pymysql 连接 Mysql 数据库及 简单的增删改查操作

    1.通过 pip 安装 pymysql 进入 cmd  输入  pip install pymysql   回车等待安装完成: 安装完成后出现如图相关信息,表示安装成功. 2.测试连接 import ...

  9. 通过flask实现web页面简单的增删改查bootstrap美化版

    通过flask实现web页面简单的增删改查bootstrap美化版 项目目录结构 [root@node1 python]# tree -L 2 . ├── animate.css ├── fileut ...

  10. 通过flask实现web页面简单的增删改查

    通过flask实现web页面简单的增删改查 # 1.后台程序falsk_web01.py #coding:utf-8 from flask import Flask,render_template,r ...

随机推荐

  1. leetcode703

    class KthLargest { public: KthLargest(int k, vector<int> nums) { size = k; for(auto num:nums){ ...

  2. Shiro异常处理总结

    出自:https://blog.csdn.net/goodyuedandan/article/details/62420120 一.Spring MVC处理异常有3种方式: (1)使用Spring-M ...

  3. tree的所有节点都勾选上或者取消勾选

    还有一个功能,就是让tree的所有节点都勾选上或者取消勾选,在api中找了一下有一个方法: check target 选中指定节点. 那我们只能是选中根节点后,实现全选. getRoot none 获 ...

  4. java aop 日志打印 正则设置

    package tz.lion.Utils.aop; import com.alibaba.fastjson.JSON;import org.springframework.web.multipart ...

  5. manta api

    Authentication 有几个访问方法. 验证对服务的请求的主要方法是使用TLS上的HTTP签名. 在大多数情况下,您只需使用SSH私钥对HTTP Date标头的小写日期:和值进行签名; 这样做 ...

  6. Kafka核心概念(转)

    转自:https://blog.csdn.net/liyiming2017/article/details/82805479 1.Kafka集群结构 实际上kafka的结构图是有些区别的,现在我们看下 ...

  7. Android开发实战之ViewPager的轮播

    在安卓开发的许多控件中,如果你没有使用过ViewPager,就不能算是一个安卓开发工程师,在本篇博文中,我会总结ViewPager的使用方法, 以及一些开发中的拓展.希望本篇博文对你的学习和工作有所帮 ...

  8. 【bzoj3239】Discrete Logging

    [吐槽] 这题和[bzoj]2480一毛一样. 就是输入顺序和输出变了一下. 传送门:http://www.cnblogs.com/chty/p/6043707.html

  9. Nginx 源码完全注释(11)ngx_spinlock

    Nginx 是多进程模式的,一个 master 与多个 workers,一般工作在多核 CPU 上,所以自旋锁就是必须用到的.Nginx 中的自旋锁的定义,位于 ngx_spinlock.c 中,如下 ...

  10. 92. Reverse Linked List II (List)

    Reverse a linked list from position m to n. Do it in-place and in one-pass. For example: Given 1-> ...