gpt4 book ai didi

java - 如何在其他线程上正确执行数据库调用?

转载 作者:搜寻专家 更新时间:2023-10-30 22:35:46 25 4
gpt4 key购买 nike

我真的很困惑我应该如何在我的 Android 应用程序中使用线程来进行数据库交互。资源太多,不知道选哪个。因此,我希望针对我的具体情况获得更具体、更有针对性的建议,这样我就有了一个起点。

这是我的数据库类结构,到目前为止效果很好:

public class DatabaseHelper extends SQLiteOpenHelper {
private static volatile SQLiteDatabase mDatabase;
private static DatabaseHelper mInstance = null;
private static Context mContext;

private static final String DB_NAME = "database.db";
private static final int DB_VERSION = 1;

private static final DB_CREATE_THINGY_TABLE = "CREATE TABLE blahblahblah...";
//other various fields here, omitted

public static synchronized DatabaseHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new DatabaseHelper(context.getApplicationContext());
try {
mInstance.open();
}
catch (SQLException e) {
e.printStackTrace();
}
}
return mInstance;
}

private DatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
mContext = context;
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DB_CREATE_THINGY_TABLE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}

@Override
public void onConfigure(SQLiteDatabase db){
super.onConfigure(db);
db.setForeignKeyConstraintsEnabled(true);
}

public void open() throws SQLException {
mDatabase = getWritableDatabase();
}

public void close() {
mDatabase.close();
}

public long addNewThingy(String name) {
ContentValues values = new ContentValues();
values.put(DatabaseHelper.THINGY_COLUMN_NAME, name);
return mDatabase.insertWithOnConflict(DatabaseHelper.THINGY_TABLE, null, values, SQLiteDatabase.CONFLICT_IGNORE);
}

public Thingy getThingyById(long id) {
Cursor cursor = mDatabase.query(
DatabaseHelper.THINGY_TABLE, // table
new String[]{DatabaseHelper.THINGY_COLUMN_ID, DatabaseHelper.THINGY_COLUMN_NAME}, // column names
DatabaseHelper.THINGY_COLUMN_ID + " = ?", // where clause
new String[]{id + ""}, // where params
null, // groupby
null, // having
null); // orderby
cursor.moveToFirst();
Thingy thingy = null;
if (!cursor.isAfterLast()) {
String name = getStringFromColumnName(cursor, DatabaseHelper.THINGY_COLUMN_NAME);
thingy = new Thingy(id, name);
cursor.moveToNext();
}
cursor.close();
return thingy;
}

}

因此,只要我想访问数据库,我就会执行 mDatabaseHelper = DatabaseHelper.getInstance(context); 并且我很高兴。我不会对 open()close() 或类似的任何内容进行任何显式调用。但是现在我正在 UI 线程上进行所有数据库调用,我相信(在我的 onCreate 或 onCreateView 方法或不调用任何新线程或任何东西的单独方法中)。

我该如何正确地使这个线程化,这样我就不会在 UI 线程上执行数据库操作?

我认为我必须更改所有数据库调用才能基本上执行此操作:

  1. 首先对我的数据库类进行任何必要的编辑,以确保它在多个线程试图同时执行操作的情况下能够正常工作。我已经尝试过让我的类(class)成为单例(无论如何我认为它是单例?)并使用诸如“volatile”和“synchronized”之类的关键字,但也许我在某处遗漏了一些东西。

  2. 在自己的线程中执行数据库操作。

  3. 以某种方式在适当的函数/Activity/fragment 中触发额外的代码,这些代码将在数据库操作完成后执行。

  4. 使整个过程足够灵活,我可以在任何地方进行。

我说的有道理吗?这是处理这一切的正确方法吗?有没有一个简单的例子可以告诉我如何正确地做一些事情,比如 mThingy = mDatabaseHelper.getThingyById(id);mDatabaseHelper.addNewThingy(someName); 来自使用适当线程的示例 Activity/fragment/等?

最佳答案

使用线程的简单解决方案

public class DatabaseHelper extends SQLiteOpenHelper {
//...

public void addNewThingyAsync(final String name, final Callback<Long> cb) {
new Thread(new Runnable(){
@Override
public void run(){
cb.callback(addNewThingy(name));
}
}).start();
}

private synchronized long addNewThingy(String name){
//implementation...
}

public void getThingyByIdAsync(final long id, final Callback<Thingy> cb) {
new Thread(new Runnable(){
@Override
public void run(){
cb.callback(getThingyById(id));
}
}).start();
}

private synchronized Thingy getThingyById(long id) {
//implementation...
}

public interface Callback<T> {
public void callback(T t);
}
}

使用 AsyncTasks 的解决方案

与上述相同,但有以下变化:

public class DatabaseHelper extends SQLiteOpenHelper {
//...

public void addNewThingyAsync(final String name, final Callback<Long> cb) {
new AsyncTask<Void, Void, Long>(){
@Override
protected Long doInBackground(Void... ignoredParams) {
return addNewThingy(name);
}

@Override
protected void onPostExecute(Long result) {
cb.callback(result);
}
}.execute();
}

//...

public void getThingyByIdAsync(final long id, final Callback<Thingy> cb) {
new AsyncTask<Void, Void, Thingy>(){
@Override
protected Thingy doInBackground(Void... ignoredParams) {
return getThingyById(id);
}

@Override
protected void onPostExecute(Thingy result) {
cb.callback(result);
}
}.execute();
}
//...
}

调用(适用于两种方法)

long mId = ...; 
mDatabaseHelper = DatabaseHelper.getInstance(context);
mDatabaseHelper.getThingyByIdAsync(mId, new Callback<Thingy>{
@Override
public void callback(Thingy thingy){
//do whatever you want to do with thingy
}
});

关于java - 如何在其他线程上正确执行数据库调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37616627/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com