java如何在其他线程上正确执行数据库调用?
我真的很困惑,我应该如何在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线程上执行数据库操作
我想我必须更改所有数据库调用才能基本做到这一点:
首先对数据库类进行任何必要的编辑,以确保它在多个线程试图同时执行操作的情况下正常工作。我已经试着让我的班级成为一个单身学生(不管怎样,我认为这是一个单身学生?)使用“volatile”和“synchronized”之类的关键词,但也许我遗漏了什么
在自己的线程中执行数据库操作
以某种方式触发相应函数/活动/片段中的附加代码,这些代码将在数据库操作完成后执行
使整个过程足够多功能,我可以在任何地方进行
我说得通吗?这样做对吗?有没有一个简单的例子可以告诉我,例如,如何正确地使用适当的线程从一个示例活动/片段/etc执行mThingy = mDatabaseHelper.getThingyById(id);
或mDatabaseHelper.addNewThingy(someName);
之类的操作
# 1 楼答案
只需在UI线程外执行任何数据库操作。一种常见的技术涉及
AsyncTask
。例如:并使用它(例如,在
Activity
内):# 2 楼答案
使用线程的简单解决方案
使用异步任务的解决方案
同上,但有以下变化:
调用(两种方法都适用)