Подтвердить что ты не робот

Когда вызывается метод SQLiteOpenHelper onCreate?

Я попытался создать базу данных SQLite и сделать с ней кое-что. Но я обнаружил, что мой метод onCreate даже не вызывается!!

Я отправляю сообщение в LogCat в начале метода onCreate.

Мое предположение заключается в том, что конструктор (супер) вызовет метод 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;
    }

}
4b9b3361

Ответ 1

В документации говорится:

База данных фактически не создается или не открывается до тех пор, пока одна из getWritableDatabase() или getReadableDatabase() не будет называется.

Ответ 2

Вы правы, конструктор (супер) будет вызывать метод 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

Как говорится в официальных документах: getWritableDatabase() Создать и/или открыть базу данных, которая будет использоваться для чтения и записи. При первом вызове база данных будет открыта и onCreate (SQLiteDatabase), onUpgrade (SQLiteDatabase, int, int) и/или onOpen (SQLiteDatabase). "

После успешного открытия база данных кэшируется, поэтому вы можете вызывать этот метод каждый раз, когда вам нужно писать в базу данных. (Обязательно вызовите функцию close(), когда вам больше не нужна база данных.) Ошибки, такие как неправильные разрешения или полный диск, могут привести к сбою этого метода, но будущие попытки могут быть успешными, если проблема исправлена.

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

Ответ 4

Позвольте мне очистить логический поток. Вот концепция Lazy-initialization.

Конструктор (супер) на DatabaseHandler не будет вызывать метод onCreate. Вызов конструктора DatabaseHandler инициализирует: контекст, имя базы данных, factory, который создает базу данных, версию базы данных и обработчик ошибок базы данных.

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

ИЛИ

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

Ответ:. После успешной создания базы данных ваши конфигурации меняются, в следующий раз снова getReadableDatabase() или getWritableDatabase() вызывает getDatabaseLocked() и там выполняется onCreate(db) метод внутри getDatabaseLocked().

введите описание изображения здесь

Объяснение:

Вышеупомянутый метод 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 определяют вашу текущую среду (конфигурацию), и на основе вашей текущей среды они вызывают соответствующие методы для инициализации/настройки любого необходимого.

Также обратите внимание: Все методы обратных вызовов в DatabaseHandler (класс, который реализовал SQLiteOpenHelper) вызываются внутри тела getDatabaseLocked().

Исходный код SQLiteOpenHelper.java: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/database/sqlite/SQLiteOpenHelper.java

Исходный код SQLiteDatabase.java:  https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/database/sqlite/SQLiteDatabase.java

Пример: https://github.com/uddhavgautam/SQLiteBasicSample