一:创建主界面增删改查
/**
* @author zhiqiangRuan
* @ClassName
* @Date 2022/7/4
*/
class FiveActivity : BaseActivity(), View.OnClickListener {
lateinit var addData: Button
lateinit var deleteData: Button
lateinit var queryData: Button
lateinit var updataData: Button
var bookId: String? = null
override fun initView() {
addData = findViewById<Button>(R.id.add_data)
deleteData = findViewById<Button>(R.id.delete_data)
queryData = findViewById<Button>(R.id.query_data)
updataData = findViewById<Button>(R.id.update_data)
addData.setOnClickListener(this)
deleteData.setOnClickListener(this)
queryData.setOnClickListener(this)
updataData.setOnClickListener(this)
}
override fun initData() {
}
override fun getLayoutId(): Int {
return R.layout.activity_five
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.add_data -> {
//添加数据
val uri = Uri.parse("content://com.cnstrong.leke.helloworld.provider/book")
val values = contentValuesOf(
"author" to "George Martin",
"price" to 22.85,
"pages" to 1040,
"name" to "A Clash of King"
)
val newUri = contentResolver.insert(uri, values)
bookId = newUri?.pathSegments?.get(1)
}
/**
* apply函数扩展了所有的泛型对象,在闭包范围内可以任意调用该对象的任意方法,并在最后返回该对象.
主要的作用:是可以用来简化初始化对象的功能。
特别需要注意的是apply函数中表示对象本身使用的是this关键字而不是it。*/
R.id.query_data -> {
//查询数据
val uri = Uri.parse("content://com.cnstrong.leke.helloworld.provider/book")
contentResolver.query(uri, null, null, null, null)?.apply {
while (moveToNext()) {
val name = getString(getColumnIndex("name"))
val author = getString(getColumnIndex("author"))
val pages = getInt(getColumnIndex("pages"))
val price = getDouble(getColumnIndex("price"))
Log.d("FiveActivity", "book name is $name")
Log.d("FiveActivity", "book author is $author")
Log.d("FiveActivity", "book pages is $pages")
Log.d("FiveActivity", "book price is $price")
}
close()
}
}
R.id.update_data -> {
//更新数据
bookId?.let {
val uri = Uri.parse("content://com.cnstrong.leke.helloworld.provider/book/$it")
val values = contentValuesOf(
"price" to 24.05,
"pages" to 1216,
"name" to "A Storm of Swords"
)
contentResolver.update(uri,values,null,null)
}
}
R.id.delete_data->{
bookId?.let{
val uri = Uri.parse("content://com.cnstrong.leke.helloworld.provider/book/$it")
contentResolver.delete(uri,null,null)
}
}
}
}
}
二:Xml文件
<?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">
<Button
android:id="@+id/add_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add To Book" />
<Button
android:id="@+id/query_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Query From Book" />
<Button
android:id="@+id/update_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Update Book" />
<Button
android:id="@+id/delete_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Delete From Book" />
</LinearLayout>
三:自定义的MyProvider
package com.cnstrong.leke.helloworld
import android.content.ContentProvider
import android.content.ContentValues
import android.content.UriMatcher
import android.net.Uri
import java.lang.RuntimeException
/**
* @author zhiqiangRuan
* @ClassName 自定义ContentProvider
* @Date 2022/7/4
*/
class MyProvider : ContentProvider() {
private val bookDir = 0
private val bookItem = 1
private val categoryDir = 2
private val categoryItem = 3
/**
* 每一个ContentProvider定义唯一标识URI URI*/
private var dbHelper: MySqliteDataHelper? = null
private val authority = "com.cnstrong.leke.helloworld.provider"
/**UriMatcher本质上是一个文本过滤器,用在contentProvider中帮助我们过滤,分辨出查询者想要查询哪个数据表。*/
private val uriMatcher by lazy {
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
val mathcher = UriMatcher(UriMatcher.NO_MATCH)
//如果match()方法匹配content://com.cnstrong.leke.helloworld.provider/book路径,返回匹配码为1
mathcher.addURI(authority, "book", bookDir)
//如果match()方法匹配content://com.cnstrong.leke.helloworld.provider/book/通配符 路径,返回匹配码为2
mathcher.addURI(authority, "book/#", bookItem)
mathcher.addURI(authority, "category", categoryDir)
mathcher.addURI(authority, "category/#", categoryItem)
mathcher
}
/**创建数据*/
/**
* override fun onCreate(): Boolean {
dbHelper = context?.let {
MySqliteDataHelper(it, "BookStore.db", 1)
return true
}
return false
------------------------------
这里用到了Kotlin let操作符
obj.let{} 或obj?.let{}
第一种写法,如果确定obj不为null,可以使用,
第二种写法相当于java的非空判断,当obj不为空时,才执行大括号内的代码段,相对java的空判断来说简洁一些,值得使用。
//在函数体内使用it替代object对象去访问其公有的属性和方法
} */
override fun onCreate() = context?.let {
// MySqliteDataHelper(it, "BookStore.db", 1)
//要记住这个问题,自己写代码太不严谨了
dbHelper=MySqliteDataHelper(it, "BookStore.db", 1)
true
} ?: false
/**查询数据*/
override fun query(
uri: Uri,
projection: Array<out String>?,
selection: String?,
selectionArgs: Array<out String>?,
sortOrder: String?
) = dbHelper?.let {
//查询数据
val db = it.writableDatabase
val cursor = when (uriMatcher.match(uri)) {
bookDir -> db.query("Book", projection, selection, selectionArgs, null, null, sortOrder)
bookItem -> {
val bookId = uri.pathSegments[1]
db.query("Book", projection, "id=?", arrayOf(bookId), null, null, sortOrder)
}
categoryDir -> db.query(
"Category",
projection,
selection,
selectionArgs,
null,
null,
sortOrder
)
categoryItem -> {
val categoryId = uri.pathSegments[1]
db.query("Category", projection, "id=?", arrayOf(categoryId), null, null, sortOrder)
}
else->null
}
cursor
}
/**
* 得到数据类型*/
override fun getType(uri: Uri) = when (uriMatcher.match(uri)) {
bookDir -> "vnd.android.cursor.dir/vnd.com.cnstrong.leke.helloworld.provider.book"
bookItem -> "vnd.android.cursor.item/vnd.com.cnstrong.leke.helloworld.provider.book"
categoryDir -> "vnd.android.cursor.dir/vnd.com.cnstrong.leke.helloworld.provider.category"
categoryItem -> "vnd.android.cursor.item/vnd.com.cnstrong.leke.helloworld.provider.category"
else -> null
}
/**插入数据
*
* override fun insert(uri: Uri, values: ContentValues?): Uri? {
//获取到SQLiteDatabase 对象
val db = dbHelper?.writableDatabase
val uriReturn = when (uriMatcher.match(uri)) {
bookDir, bookItem -> {
val newBookId = db?.insert("Book", null, values)
Uri.parse("content://$authority/book/$newBookId")
}
categoryDir, categoryItem -> {
val newCategoryId = db?.insert("Category", null, values)
Uri.parse("content://$authority/category/$newCategoryId")
}
else -> null
}
return uriReturn
}*/
override fun insert(uri: Uri, values: ContentValues?) = dbHelper?.let {
//获取到SQLiteDatabase 对象
val db = it.writableDatabase
val uriReturn = when (uriMatcher.match(uri)) {
bookDir, bookItem -> {
val newBookId = db.insert("Book", null, values)
Uri.parse("content://$authority/book/$newBookId")
}
categoryDir, categoryItem -> {
val newCategoryId = db.insert("Category", null, values)
Uri.parse("content://$authority/category/$newCategoryId")
}
else ->null
}
uriReturn
}
/**删除数据*/
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?) =
dbHelper?.let {
//删除数据
val db = it.writableDatabase
val deleteRows = when (uriMatcher.match(uri)) {
bookDir -> db.delete("Book", selection, selectionArgs)
bookItem -> {
//筛选条件参数
val bookId = uri.pathSegments[1]
db.delete("Book", "id=?", arrayOf(bookId))
}
categoryDir -> db.delete("Category", selection, selectionArgs)
categoryItem -> {
val categoryId = uri.pathSegments[1]
db.delete("Category", "id=?", arrayOf(categoryId))
}
else -> 0
}
deleteRows
} ?: 0
/**更新数据*/
override fun update(
uri: Uri,
values: ContentValues?,
selection: String?,
selectionArgs: Array<out String>?
) = dbHelper?.let {
val db = it.writableDatabase
val updateRows = when (uriMatcher.match(uri)) {
bookDir -> db.update("Book", values, selection, selectionArgs)
bookItem -> {
val bookId = uri.pathSegments[1]
db.update("Book", values, "id=?", arrayOf(bookId))
}
categoryDir -> db.update("Category", values, selection, selectionArgs)
categoryItem -> {
val categoryId = uri.pathSegments[1]
db.update("Category", values, "id=?", arrayOf(categoryId))
}
else -> 0
}
updateRows
} ?: 0
}
四:MySqliteDataHelper 数据库创建的帮助类
package com.cnstrong.leke.helloworld
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.widget.Toast
/**
* @author zhiqiangRuan
* @ClassName
* kotlin 构造函数 参数
* val context: Context 上下文
* name: String 数据库名,库名 xxx.db
* version: Int 版本号,用来数据库升级的
* @Date 2022/7/4
*/
class MySqliteDataHelper(val context: Context, name: String, version: Int) :
SQLiteOpenHelper(context, name, null, version) {
private val book = "create table Book( " +
"id integer primary key autoincrement," +
"author text," +
"price real," +
"pages integer," +
"name text)"
private val category = "create table Category( " +
"id integer primary key autoincrement," +
"category_name text," +
"category_code integer)"
/**使用SQliteDatabase创建数据表
*
* 1.这个方法,第一次打开数据库时候才会走
* 2.在清除数据之后再一次运行-->打开数据库,这个方法会走
* 3.没有清除数据,不会走这个方法
* 4.数据库升级的时候这个方法不会走
* */
override fun onCreate(db: SQLiteDatabase?) {
db?.execSQL(book)
db?.execSQL(category)
Toast.makeText(context, "create books success", Toast.LENGTH_SHORT).show()
}
/**
* 1.第一次创建数据库的时候,这个方法不会走
*
*2.清除数据再次运行(相当于第一次创建)这个方法不会走
*
* 3.数据库已经存在,而且版本升高的时候,这个方法才会调用*/
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
//根据版本号判断
if (oldVersion <= 1) {
db?.execSQL("alter table Book add column category_id")
}
}
/**这个方法是数据库降级操作
*
* 1.新版本比旧版本低时候才会执行
*
* 2.如果不执行降级操作会抛出异常*/
override fun onDowngrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
super.onDowngrade(db, oldVersion, newVersion)
}
}
五:MyProvider的AndroidManifest配置
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cnstrong.leke.helloworld">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication"
android:usesCleartextTraffic="true">
<activity android:name=".FiveActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".FirstActivity" />
<activity
android:name=".ThirdActivity"
android:screenOrientation="landscape" />
<provider
android:name=".MyProvider"
android:authorities="com.cnstrong.leke.helloworld.provider"
android:enabled="true"
android:exported="true">
</provider>
</application>
</manifest>
六:遇到的问题
不知道什么原因,有大神知道吗,需要指导一下
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。