乐趣区

关于android:Android-Kotlin语言学习第三课自定义ContentProvider和SQlite学习增删改查

一:创立主界面增删改查

/**
 * @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>

六:遇到的问题

不晓得什么起因,有大神晓得吗,须要领导一下

退出移动版