Android-ContentProvider簡單的增刪改查


 

注意:在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應用的數據庫

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM