【发布时间】:2016-10-03 15:40:06
【问题描述】:
我真的很困惑我应该如何在我的 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 线程上执行数据库操作?
我认为我必须更改所有数据库调用才能基本上做到这一点:
首先对我的数据库类进行任何必要的编辑,以确保它在多个线程尝试同时执行操作的情况下能够正常工作。我已经尝试过让我的班级成为单例(无论如何我认为它是单例?)并使用诸如“易失性”和“同步”之类的关键字,但也许我在某处遗漏了一些东西。
在自己的线程中执行数据库操作。
以某种方式在适当的函数/活动/片段中触发额外的代码,一旦数据库操作完成,这些代码将执行。
让整个过程足够灵活,让我可以在任何地方进行。
我说得有道理吗?这是处理这一切的正确方法吗?您是否可以制作一个简单的示例来向我展示如何使用正确的线程从示例活动/片段/等中正确执行mThingy = mDatabaseHelper.getThingyById(id); 或mDatabaseHelper.addNewThingy(someName); 之类的操作?
【问题讨论】:
-
如果需要几毫秒,我认为在主线程上执行
mThingy = mDatabaseHelper.getThingyById(id);或mDatabaseHelper.addNewThingy(someName);没有任何问题。安卓也不行。与网络操作相反,平台不会阻止主线程上的数据库操作。不过,如果您在其他线程上需要它,请使用AsyncTask。 -
我知道,在这个简单的例子中,它在主线程上已经足够快了,但对于其他函数,我使用更复杂的标准检索整个对象列表,因此可能需要更多时间。在应用程序的其他领域,我还进行文件操作(涉及位图/重新缩放等),所以我仍然想了解如何正确处理这些。
-
我确实研究了 AsyncTask,但我不明白如何在我的情况下正确使用它。我也不明白参数 AsyncTask
和看起来像 Int...等的奇怪参数。
标签: java android database multithreading sqlite