web-dev-qa-db-ja.com

SQLiteOpenHelper onCreateメソッドが呼び出されたとき?

私はSQLiteデータベースを作成し、それを使っていくつかのことを試みました。しかし、私はonCreateメソッドが呼び出されてさえいないことを発見しました!!

onCreateメソッドの開始時にメッセージをLogCatに送信しています。

私の仮定は、(スーパー)コンストラクターがonCreateメソッドを呼び出すことです。そうですか?

私のコード:

import Android.database.sqlite.SQLiteOpenHelper;
import Android.database.sqlite.SQLiteDatabase;
import Android.content.Context;
import Android.database.Cursor;
import Android.content.ContentValues;
import Android.util.Log;

public class DatabaseHandler extends SQLiteOpenHelper {
    // Static Constants
    /*** Database details ***/
    // Database version
    private static final int DATABASE_VERSION           = 1;

    // Database name
    private static final String DATABASE_NAME           = "database_name";

    /*** Database Tables ***/
    /** Events **/
    // Event table
    private static final String TABLE_EVENT             = "event";

    // Event table columns
    private static final String COLUMN_EVENT_EID        = "_eid";

    private static final String COLUMN_EVENT_CREATION_DATE  = "creation_date";

    private static final String COLUMN_EVENT_TITLE      = "title";
    private static final String COLUMN_EVENT_ICON       = "icon";

    public DatabaseHandler(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.e("MyApp", "onCreate invoked");
        // Tables creation queries
        String CREATE_EVENT_TABLE = "create table " + TABLE_EVENT + "(" + COLUMN_EVENT_EID + " integer primary key, "
                + COLUMN_EVENT_CREATION_DATE + " text, "
                + COLUMN_EVENT_TITLE + " text, "
                + COLUMN_EVENT_ICON + " text)";

        // Creating tables
        db.execSQL(CREATE_EVENT_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.e("MyApp", "onUpgrade invoked");
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_EVENT);
    }
}

MainActivityコード:

import Android.os.Bundle;
import Android.app.Activity;
import Android.view.Menu;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DatabaseHandler db = new DatabaseHandler(this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}
27
malhobayyeb

documentation はこう言っています:

getWritableDatabase() または getReadableDatabase() のいずれかが呼び出されるまで、データベースは実際には作成または開かれません。

30
CL.

そうです、(スーパー)コンストラクターはonCreateメソッドを呼び出しますが、実際のデータベースが存在しない場合のみです。から http://developer.Android.com/reference/Android/database/sqlite/SQLiteOpenHelper.html#onCreate%28Android.database.sqlite.SQLiteDatabase%29

データベースの作成とバージョン管理を管理するヘルパークラス。

OnCreate(SQLiteDatabase)、onUpgrade(SQLiteDatabase、int、int)およびオプションでonOpen(SQLiteDatabase)を実装するサブクラスを作成し、このクラスはデータベースが存在する場合はそれを開き、存在しない場合は作成し、必要に応じてアップグレードします。 。

3
Ricardo Rivaldo

ロジックフローについて説明します。これがLazy-initializationの概念です。

DatabaseHandlerの(スーパー)コンストラクターは、onCreateメソッドを呼び出しません。 DatabaseHandlerコンストラクターを呼び出すと、初期化されます:コンテキスト、データベース名、データベースを作成するファクトリー、データベースバージョン、およびデータベースエラーハンドラー。

getWritableDatabase()>getDatabaseLocked()>-SQLiteDatabase.create()

OR

getReadableDatabase()>getDatabaseLocked()>-SQLiteDatabase.create()

Answer:データベースが正常に作成されると、構成が変更され、次にgetReadableDatabase()またはgetWritableDatabase()getDatabaseLocked()を呼び出し、onCreate(db)内のgetDatabaseLocked()メソッドが実行されます。

enter image description here

説明:

上記のSQLiteDatabase.create()メソッドは、ディスクにSQLiteDatabaseを作成します。

しかし、遅延初期化のプロセス(つまり、すべての準備ができるわけではありません。必要に応じて、ランタイム上にオブジェクトを作成します。このため、多くのif..elseステートメントを使用しました)。

getDatabaseLocked()の全体が表示されている場合は、以下のとおりです。 [onCreate()の本体内でgetDatabaseLocked()メソッドを検索できます]

private SQLiteDatabase getDatabaseLocked(boolean writable) {
        if (mDatabase != null) {
            if (!mDatabase.isOpen()) {
                // Darn!  The user closed the database by calling mDatabase.close().
                mDatabase = null;
            } else if (!writable || !mDatabase.isReadOnly()) {
                // The database is already open for business.
                return mDatabase;
            }
        }

        if (mIsInitializing) {
            throw new IllegalStateException("getDatabase called recursively");
        }

        SQLiteDatabase db = mDatabase;
        try {
            mIsInitializing = true;

            if (db != null) {
                if (writable && db.isReadOnly()) {
                    db.reopenReadWrite();
                }
            } else if (mName == null) {
                db = SQLiteDatabase.create(null);
            } else {
                try {
                    if (DEBUG_STRICT_READONLY && !writable) {
                        final String path = mContext.getDatabasePath(mName).getPath();
                        db = SQLiteDatabase.openDatabase(path, mFactory,
                                SQLiteDatabase.OPEN_READONLY, mErrorHandler);
                    } else {
                        db = mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ?
                                Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0,
                                mFactory, mErrorHandler);
                    }
                } catch (SQLiteException ex) {
                    if (writable) {
                        throw ex;
                    }
                    Log.e(TAG, "Couldn't open " + mName
                            + " for writing (will try read-only):", ex);
                    final String path = mContext.getDatabasePath(mName).getPath();
                    db = SQLiteDatabase.openDatabase(path, mFactory,
                            SQLiteDatabase.OPEN_READONLY, mErrorHandler);
                }
            }

            onConfigure(db);

            final int version = db.getVersion();
            if (version != mNewVersion) {
                if (db.isReadOnly()) {
                    throw new SQLiteException("Can't upgrade read-only database from version " +
                            db.getVersion() + " to " + mNewVersion + ": " + mName);
                }

                db.beginTransaction();
                try {
                    if (version == 0) {
                        onCreate(db);
                    } else {
                        if (version > mNewVersion) {
                            onDowngrade(db, version, mNewVersion);
                        } else {
                            onUpgrade(db, version, mNewVersion);
                        }
                    }
                    db.setVersion(mNewVersion);
                    db.setTransactionSuccessful();
                } finally {
                    db.endTransaction();
                }
            }

            onOpen(db);

            if (db.isReadOnly()) {
                Log.w(TAG, "Opened " + mName + " in read-only mode");
            }

            mDatabase = db;
            return db;
        } finally {
            mIsInitializing = false;
            if (db != null && db != mDatabase) {
                db.close();
            }
        }
    }

ご注意くださいgetDatabaseLocked()メソッドの本体内には、if .. elseケースが非常に多くあります。これらのif .. elseケースは現在の環境(構成)を決定し、現在の環境に基づいて、必要なものを初期化/構成するための適切なメソッドを呼び出します。

また、注意:DatabaseHandlerSQLiteOpenHelperを実装したクラス)のすべてのコールバックメソッドは、getDatabaseLocked()内で呼び出されます体。

ソースコードSQLiteOpenHelper.Javahttps://Android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/Java/Android/database/sqlite/SQLiteOpenHelper.Java

ソースコードSQLiteDatabase.Javahttps://Android.googlesource.com/platform/frameworks/base/+/master/core/Java/Android/database/sqlite/SQLiteDatabase.Java

従うべきサンプル: https://github.com/uddhavgautam/SQLiteBasicSample

3
Uddhav Gautam

公式ドキュメントにあるように、「getWritableDatabase()読み取りと書き込みに使用されるデータベースを作成および/または開きます。これが初めて呼び出されたとき、データベースが開かれ、onCreate(SQLiteDatabase)、onUpgrade(SQLiteDatabase、int、int)、onOpen(SQLiteDatabase)が呼び出されます。

正常に開くと、データベースがキャッシュされるため、データベースに書き込む必要があるたびにこのメソッドを呼び出すことができます。 (データベースが不要になった場合は、必ずclose()を呼び出してください。)不正なアクセス権やディスク全体などのエラーにより、このメソッドは失敗する可能性がありますが、問題が修正されれば、今後の試行は成功する可能性があります。

http://developer.Android.com/reference/Android/database/sqlite/SQLiteOpenHelper.html#getWritableDatabase()

1
Sam003