关于 SQLiteOpenHelper 的自创建数据库目录文件

在 android 中有个类可方便的直接创建数据库,自己写一个类继承 SQLiteOpenHelper
package com.wangban.yzbbanban.test_mysqlite;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;

/**
 * Created by YZBbanban on 16/7/27.
 */

public class MySQLiteHelper extends SQLiteOpenHelper {
    private Context context;

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

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL("create table Book(id integer primary key autoincrement,name text,price real)");
        Toast.makeText(context, "创建完成", Toast.LENGTH_SHORT).show();
    }

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

    }
}

代码很简单,传入一个 Context(此 Context 很重要),创建一个对象,传入参数:上下文对象,数据库文件名,游标工厂(一般不用,为 null),数据库版本号(可自定义),

重写 onCreate 的方法,方法的参数即为数据库引用,可用此引用创建数据库中的表单:exeSQL()方法创建表单数据,创建成功,Toast 提示一下,onUpgrade 表示,若版本号与之前的老版本号不一致,则执行此方法(在此不需要用)。至此一个 MySQLiteHelper类完成,用于创建数据库文件,以及表单。

现在进入正题,之前提到过构造方法的一个传入值Context,我们可以在源码中找到一个这样的类:ContextWrapper (继承自 Context)通过此类我们可以获得应用程序的资源和类,包括对Activity,Broadcast,Intent等的操做,比如 startActivity(),sendBroadcast()等,还有些设置方法,像是setWallpaper(),当然最主要是有关于数据存储的一切方法:文件存储(File),个性化存储(sharedPreferances),数据库 (SQLite)等,对于数据库的操作直接看源码:

  public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
        throw new RuntimeException("Stub!");
    }

    public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory, DatabaseErrorHandler errorHandler) {
        throw new RuntimeException("Stub!");
    }

    public boolean moveDatabaseFrom(Context sourceContext, String name) {
        throw new RuntimeException("Stub!");
    }

    public boolean deleteDatabase(String name) {
        throw new RuntimeException("Stub!");
    }

    public File getDatabasePath(String name) {
        throw new RuntimeException("Stub!");
    }

    public String[] databaseList() {
        throw new RuntimeException("Stub!");
    }

构造方法:

public class ContextWrapper extends Context {
    public ContextWrapper(Context base) {
        throw new RuntimeException("Stub!");
    }

可以知道构造方法只有一个参数 Context,而且,在 SQLiteOpenHelper 中传入的 Context,也是在此调用的,其中的具体方法被SDK 隐藏了,所以看不到,只有抛出异常,但是可以了解到:所以在创建数据库时需要传入一个参数:Context, 其中getDatabasePath() 为创建数据库路径,OpenOrCreateDatebase ()为创建数据库,所以也可以确认的是,在 SQLiteOpenHelper 中的子类,调用getReadableDatabase()生成数据库文件表单时也调用了OpenOrCreateDatebase (),同样传入参数也是 Context,(只是默认路径在该程序的数据库文件夹里(data/data/~~)),所以我们只要重写了 ContextWrapper 方法,并重写其中的 OpenCreateDatebase(),与 getDatabasePath()方法即可创建所需要的数据库目录与数据库表单,下面是代码:
package com.wangban.yzbbanban.test_mysqlite;

import android.content.Context;
import android.content.ContextWrapper;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import java.io.File;
import java.io.IOException;

/**
 * Created by YZBbanban on 16/7/27.
 */

public class MyContextWrapper extends ContextWrapper {
    private Context mContext;
    private String dirName;

    /**
     * 构造函数
     *
     * @param base
     *			上下文环境
     */
    public MyContextWrapper(Context base) {
        super(base);
        this.mContext = base;
    }
    /**
     * 构造函数
     * @param base
     * @param dirName
     */
    public MyContextWrapper(Context base, String dirName) {
        super(base);
        this.mContext = base;
        this.dirName = dirName;
    }

    /**
     * 获得数据库路径,如果不存在,则创建对象对象
     *
     * @param name
     */
    @Override
    public File getDatabasePath(String name) {
        // 判断是否存在sd卡
        boolean sdExist = android.os.Environment.MEDIA_MOUNTED
                .equals(android.os.Environment.getExternalStorageState());
        if (!sdExist) {// 如果不存在,
            Log.e("SD卡管理:", "SD卡不存在,请加载SD卡");
            return null;
        } else {// 如果存在
            // 获取sd卡路径
            String dbDir = android.os.Environment.getExternalStorageDirectory()
                    .getAbsolutePath();
            dbDir += "/" + ((dirName == null || "".equals(dirName)) ?
                    mContext.getPackageName() : dirName);// 数据库所在目录
            String dbPath = dbDir + "/" + name;// 数据库路径
            // 判断目录是否存在,不存在则创建该目录
            File dirFile = new File(dbDir);
            if (!dirFile.exists())
                dirFile.mkdirs();

            // 数据库文件是否创建成功
            boolean isFileCreateSuccess = false;
            // 判断文件是否存在,不存在则创建该文件
            File dbFile = new File(dbPath);
            if (!dbFile.exists()) {
                try {
                    isFileCreateSuccess = dbFile.createNewFile();// 创建文件
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } else
                isFileCreateSuccess = true;

            // 返回数据库文件对象
            if (isFileCreateSuccess)
                return dbFile;
            else
                return null;
        }
    }

    /**
     * 重载这个方法,是用来打开SD卡上的数据库的,android 2.3及以下会调用这个方法。
     *
     * @param name
     * @param mode
     * @param factory
     */
    @Override
    public SQLiteDatabase openOrCreateDatabase(String name, int mode,
                                               SQLiteDatabase.CursorFactory factory) {
        SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(
                getDatabasePath(name), null);
        return result;
    }

    /**
     * Android 4.0会调用此方法获取数据库。
     *
     * @see android.content.ContextWrapper#openOrCreateDatabase(java.lang.String,
     *	  int, android.database.sqlite.SQLiteDatabase.CursorFactory,
     *	  android.database.DatabaseErrorHandler)
     * @param name
     * @param mode
     * @param factory
     * @param errorHandler
     */
    @Override
    public SQLiteDatabase openOrCreateDatabase(String name, int mode,
                                               SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) {
        SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(
                getDatabasePath(name), null);
        return result;
    }
}
在 Activity 中创建 MySQLiteHelper()对象,并使用新的 Context 对象传入MySQLiteHelper的 onCreate() 方法中即可,下面是 Activity 代码:
package com.wangban.yzbbanban.test_mysqlite;

import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;


public class MainActivity extends AppCompatActivity {
    private Button btnCreate;
    private MySQLiteHelper helper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btnCreate = (Button) findViewById(R.id.btn_create);
        MyContextWrapper mContext = new MyContextWrapper(this, "Run");
        helper = new MySQLiteHelper(mContext, "Book.db", null, 2);
        setListeners();

    }

    private void setListeners() {
        btnCreate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                SQLiteDatabase db = helper.getWritableDatabase();
            }
        });
    }
}
布局文件:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.wangban.yzbbanban.test_mysqlite.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintLeft_toLeftOf="@+id/activity_main"
        app:layout_constraintTop_toTopOf="@+id/activity_main"
        app:layout_constraintRight_toRightOf="@+id/activity_main"
        app:layout_constraintBottom_toBottomOf="@+id/activity_main" />

    <Button
        android:text="创建"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn_create"
        app:layout_constraintLeft_toLeftOf="@+id/activity_main"
        android:layout_marginLeft="16dp"
        android:layout_marginStart="16dp"
        app:layout_constraintTop_toTopOf="@+id/activity_main"
        android:layout_marginTop="16dp"
        app:layout_constraintRight_toRightOf="@+id/activity_main"
        android:layout_marginRight="16dp"
        android:layout_marginEnd="16dp" />

</android.support.constraint.ConstraintLayout>


猜你喜欢

转载自blog.csdn.net/u013377003/article/details/52050189