Android網絡與數據存儲_學習筆記_第六週:SQLite與ContentProvider

SQLite

什麼是SQLite數據庫?
特色:

輕量級、獨立、隔離、跨平臺、多語言接口、安全性。

如何和數據庫打交道
1、設計數據庫與表

創建數據庫
DatabaseHelper類

public class DatabaseHelper extends SQLiteOpenHelper {
    public DatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

MainActivity類

Android提供了一個名爲SQLiteDatabase的類,該類封裝了一些操作數據庫的API,使用該類可以完成對數據進行添加(Create)、查詢(Retrieve)、更新(Update)和刪除(Delete)操作(這些操作簡稱爲CRUD)。對SQLiteDatabase的學習,我們應該重點掌握execSQL()和rawQuery()方法。 execSQL()方法可以執行insert、delete、update和CREATE TABLE之類有更改行爲的SQL語句; rawQuery()方法用於執行select語句。

     DatabaseHelper databaseHelper = new DatabaseHelper(this,"test.db",null,1);
        SQLiteDatabase sqLiteDatabase = databaseHelper.getReadableDatabase();

創建表
DatabaseHelper類

   @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL("create table user(username varchar(20) not null,password varchar(60) not null)");
    }

2、對數據庫進行增刪改查
MainActivity類

package com.example.chenjinhua.sqlite;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private SQLiteDatabase sqLiteDatabase;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button add_button = (Button) findViewById(R.id.add_button);
        Button query_button = (Button) findViewById(R.id.query_button);
        Button delete_button = (Button) findViewById(R.id.delete_button);
        Button update_button = (Button) findViewById(R.id.update_button);

        add_button.setOnClickListener(this);
        query_button.setOnClickListener(this);
        delete_button.setOnClickListener(this);
        update_button.setOnClickListener(this);

        DatabaseHelper databaseHelper = new DatabaseHelper(this,"test1.db",null,1);
        sqLiteDatabase = databaseHelper.getReadableDatabase();
        Log.i("MainActivity","create db");
    }

    @Override
    public void onClick(View view) {
        switch  (view.getId()){
            //insert:
            case R.id.add_button:

                ContentValues contentValues = new ContentValues();
                contentValues.put(DatabaseHelper.USERNAME,"jinhua");
                contentValues.put(DatabaseHelper.PASSWORD, "zxcv");

                long rowNumber = sqLiteDatabase.insert(DatabaseHelper.USER_TABLE,null,contentValues);
                if ( rowNumber != -1){
                    Toast.makeText(MainActivity.this, "插入成功", Toast.LENGTH_SHORT).show();
                }
                break;

            //query
            case R.id.query_button:
            // 遊標,是要查找的數據的集合
                Cursor cursor = sqLiteDatabase.query(DatabaseHelper.USER_TABLE,null,null,null,null,null,null);
                if (cursor.moveToFirst()){
                    int count = cursor.getCount();//1、count是數據庫的所有數目;2、快捷鍵command+option+v
                    for (int i = 0; i < count; i++) {
                        String userName = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.USERNAME));
                        String password = cursor.getString(cursor.getColumnIndexOrThrow(DatabaseHelper.PASSWORD));
                        Log.i("MainActivity",i + ":" + userName + "|" + password);
                    }
                }
                break;

            //delete
            case R.id.delete_button:
                String whereClauseString = "userName = ?";
                String[] whereArgsString = {"jinhua"};
                sqLiteDatabase.delete(DatabaseHelper.USER_TABLE,whereClauseString,whereArgsString);
                break;

            //update
            case R.id.update_button:
                ContentValues contentValues1 = new ContentValues();
                contentValues1.put(DatabaseHelper.PASSWORD,"100歲");
                whereClauseString = "userName = ?";
                String[] whereArgsString1 = {"jinhua"};
                sqLiteDatabase.update(DatabaseHelper.USER_TABLE,contentValues1,whereClauseString,whereArgsString1);
        }
    }
}

除了上述方法,還可以使用原始方法,即用SQL語句。

sqLiteDatabase.execSQL("insert into user(username,age) values('張三','5歲')");

3、優化

(1) 如何設計數據庫與表

上萬條數據如何建表,比如300個城市,每個城市600條信息;

爲什麼不用文件存儲?
文件存儲弊端:文件存儲沒有規則;
數據庫優勢:a、有規則,用SQL語句即可查找;b、數據庫更新很方便,比如onUpgrade方法。

在手機端拆表,300個城市排序1個表,用二分法查表等。

(2)對數據庫進行增刪改查

a、原始SQL語句執行效率更高rawQuery execSQL;
b、只檢索有用的列、有用的行,越少越好;
c、是否排序;
d、是否創建索引。//當數據很多時需要創建索引,方便查找。

執行增刪改操作方法 :db.execSQL(sql); 或者db.insert()、db.delete()、db.update(),並且包括數據表的創建和刪除等等也可以通過execSQL實現

(3)、事務
需要操作很多數據時,用SQL很耗費性能,用事務。

 //開始事務,此時db會被鎖定,其他線程需要操作數據庫的話會失敗
        sqLiteDatabase.beginTransaction();
        try {
            //做操作
            for (int i = 0; i <1000 ; i++) {
                sqLiteDatabase.execSQL("insert into user(username,age) values('張三','5歲')");
            }
            //一定要設置成功,不設置的話會自動回滾提交
            sqLiteDatabase.setTransactionSuccessful();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //關閉事務,同時纔會向數據庫裏進行批量的提交,endTransaction即提交的意思
            sqLiteDatabase.endTransaction();
        }

(4)對象關係映射 ORM

將一個對象和關係型數據庫的一張表對應起來,這樣不需要和複雜的SQL語句打交道,只需要簡單的操作對象的屬性和方法就行。

練習:

a) 做一個登錄界面,數據庫字段包含用戶名、密碼以及是否登錄中的狀態
b) 模擬登錄成功後,將登錄的用戶名及登錄狀態(登錄中)寫入數據庫,並跳轉新頁面,有退出按鈕
c) 當點擊退出時,將當前用戶登錄中的狀態清除
d) 下一次登錄時,顯示上一次登錄的用戶名
e) 保存所有用戶登錄的歷史,但一個用戶名只保留一條記錄。

遇到報錯:

sqLiteDatabase.execSQL(“create table ” + LOGIN_TABLE + “(” +
USER_NAME + ” varchar(20) not null,” + PASSWORD + ” varchar(60) not
null,” + LOGIN_STATE + ” varchar(20) not null);”);

error: no such table。
stackoverflow查了:

simply Change Your Databse name in Data base class which you implemented Using SQliteDatabase

然後我修改了數據庫名字,然後問題就解決了。可是我還沒明白爲什麼。。


ContentProvider

一、什麼是ContentProvider?

  • 應用程序 間 共享數據的一種方式
  • 爲存儲和獲取數據提供了統一的接口
  • Android爲常見的一些數據提供了默認的ContentProvider
  • 四大組件之一

系統提供的封裝好的ContentProvider,如:sdk- samples- notePad。

ContentProvider //提供者
1、提供query(uri)、delete(uri)、insert(uri)、update(uri)方法;
2、這些方法都要傳入uri;
3、根據不同的uri做不同的db操作。

 sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        sUriMatcher.addURI(NotePad.AUTHORITY, "notes", NOTES);
        sUriMatcher.addURI(NotePad.AUTHORITY, "notes/#", NOTE_ID);
        sUriMatcher.addURI(NotePad.AUTHORITY, "live_folders/notes", LIVE_FOLDER_NOTES);

switch (sUriMatcher.match(uri)) {
           case NOTES:
               qb.setProjectionMap(sNotesProjectionMap);
               break;
           case NOTE_ID:
               qb.setProjectionMap(sNotesProjectionMap);
               qb.appendWhere(
                   NotePad.Notes._ID +    // the name of the ID column;
                   "=" + uri.getPathSegments().get(NotePad.Notes.NOTE_ID_PATH_POSITION));
               break;

           case LIVE_FOLDER_NOTES:
               qb.setProjectionMap(sLiveFolderProjectionMap);
               break;

           default:
               throw new IllegalArgumentException("Unknown URI " + uri);
       }

如何使用ContentProvider?

 /*
        1、ContentProvider就是一系列封裝的接口,把數據封裝起來,對外提供一系列增刪改查接口給別人;uri就是獲取數據的路徑。
        2、通過ContentProvider提供的query這個接口,把通訊錄裏所有聯繫人查詢出來,操作數據;
        3、ContentProvider可以用封裝的,也可以自己封裝ContentProvider,給自己應用用,也可以給其他應用程序用。
        * */
        //ContentResolver內容解析器
        ContentResolver contentResolver = getContentResolver();
        //通用資源標識符,表示資源(圖像、視頻、音頻)路徑,有3個字段表示:scheme(content://)、host(包名)、path;
        Uri uri = Uri.parse("content://com.android.contacts/contacts");
        //把這個xxx包裏面xxx這個表裏id爲10的username字段的值
        Uri uri1 = Uri.parse("content://com.example.chenjinhua.testcontentprovider/table_name/10/username");
        Cursor cursor = contentResolver.query(uri,null,null,null,null);
        if ( cursor != null && cursor.moveToFirst()){}

二、ContentProvider的實現過程

  1. Database
  2. Uri
  3. UriMatcher
  4. ContentProvider
  5. query/insert/update/delete
  6. AndroidManifest.xml

1、Database
DatabaseHelper類建立db以及兩張表

package com.example.chenjinhua.sqlite;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

/**
 * Created by chenjinhua on 16/4/3.
 */
public class DatabaseHelper extends SQLiteOpenHelper {
    public static final String USER_TABLE = "user";
    public static final String USERNAME = "username";
    public static final String PASSWORD = "password";
    public static final String BOOK_TABLE = "book_table";
    public static final String BOOK_NAME = "book_name";
    public static final String BOOK_PRICE = "book_price";

    public DatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL("create table " + USER_TABLE + "(" + USERNAME + " varchar(20) not null," + PASSWORD + " varchar(60) not null)");
        sqLiteDatabase.execSQL("create table " + BOOK_TABLE + "(" + BOOK_NAME + " varchar(20) not null," + BOOK_PRICE + " varchar(60) not null)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}

2、Uri
新建package包、包內新建TestContentProvider類和URIList類

6、AndroidManifest.xml註冊

       <provider
            android:authorities="com.example.chenjinhua.sqlite"
            android:name=".provider.TestContentProvider"/>
發佈了53 篇原創文章 · 獲贊 13 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章