一:创立主界面增删改查
/**
* @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(
"name" to "A Storm of Swords",
"pages" to 1216,
"price" to 24.05
)
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)
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>
六:遇到的问题
不晓得什么起因,有大神晓得吗,须要领导一下