我在尝试doInBackground
AsyncTask
MainActivity
时遇到虚假错误,当用户点击btnSearch
时,我会在doInBackground
中发起错误。
这里是returnCode < 0
我可能没有错误的部分,可能在1次交易后得到错误,在23次交易后可能会在记录23001处收到错误。我在尝试insertWord
之后得到了private class LoadDatabase extends AsyncTask<Object, Integer, Void
{
protected Void doInBackground(Object[] params)
{
...
my_openDb("DatabaseConnector.LoadDatabase.doInBackground");
while(scDict.hasNext())
{
int kTransactions = 0;
try
{
mDatabase.beginTransaction();
while(kTransactions < MAX_TRANSACTIONS && scDict.hasNext())
{
s = scDict.next();
count++;
long returnCode = insertWord(s); // error here **********
if(returnCode < 0)
{
if(debug) Log.w("`````Abort--can't add <",s + "> at " + count + " with RC = " + returnCode + " and KT = " + kTransactions );
my_closeDb("DatabaseConnector.LoadDatabase.doInBackground DISASTER");//$$
System.exit(0);
}
++ kTransactions;
}
mDatabase.setTransactionSuccessful();
}
catch(Exception e){ Log.w("`````", "Exception " + e.toString()); }
finally
{
mDatabase.endTransaction();
publishProgress((Integer) (int) s.charAt(0));
}
}
my_closeDb("doInBackground outer while ended");
。
insertWord
方法 long insertWord(String _word)
{
long r = -1;
ContentValues newWord = new ContentValues();
newWord.put(WORD_COLUMN_NAME, _word);
try {
// r = mDatabase.insert (TABLE_NAME,null,newWord);
r = mDatabase.insertWithOnConflict(TABLE_NAME,null,newWord,SQLiteDatabase.CONFLICT_REPLACE);
return r;
} catch (Exception e) {
if(debug)Log.w("DBC", "insert failed for <" + _word + ">");
if(debug)Log.w("DBC", "exception " + e.toString());
my_closeDb(DatabaseConnector.insertWord");
}
return -1 ; // -1 if can't insert
}
:
insertWithOnConflict
注释掉的行总是在过去工作,直到进行大修以简化代码。 (很棒的主意。)(不!)我从https://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
得到了insertWithOnConflict
的想法,他们说General method for inserting a row into the database
是insert
。
当然,我从教科书中得到了convenience method for inserting a row into the database
。 AS说它是insertWithOnConflict
。但它确实缺乏解决冲突的算法。不应该有任何冲突。当我insert
出错时,我对DatabaseConnector
进行了更改。
这可能是我第一次警告我在冰上。
我从MainActivity
拨打DatabaseHelper
,调用内部类:LoadDatabase
,调用doInBackground
然后调用AsyncTask
。
我不确定我应该MainActivity
如此直接与AsyncTask
相关联,因为答案和评论表明并发问题可能是一个问题。
另一个建议是将MainActivity
放在DatabaseConnector
内。这意味着我也必须在那里移动类AsyncTask
及其内部类。如果这一切看起来过于复杂,我只是按照教科书中的大样例。但是你必须将数据库连接到活动,你需要帮助,如果任务必须在后台运行,那么它必须是MainActivity
,正如我所理解的那样。
来自dbc = new DatabaseConnector(MainActivity.this, getAssets(), databaseFileExists());
的电话:
public DatabaseConnector(Context _context, AssetManager _assets, boolean dbExists)
{
mContext = _context;
mDbOpenHelper = new DbOpenHelper(_context, DATABASE_NAME, null, 1);
SQLiteDatabase db = mDbOpenHelper.getWritableDatabase();
if( ! dbExists)
createAndOrFillDb(db);
}
在DatabaseConnector中:
createAndOrFillDb
void createAndOrFillDb(SQLiteDatabase db)
{
...
db.execSQL("CREATE TABLE " + TABLE_NAME + "(" + WORD_COLUMN_NAME + " TEXT primary key );")
//...
cursor = db.query(TABLE_NAME, mColumns, null, null, null, null, WORD_COLUMN_NAME);
//...
LoadDatabase
__loadDb;
__loadDb = new LoadDatabase();
__loadDb.execute((Object[]) null);
}
:
doInBackground
所以我的问题是
(1)您是否认为我在MainActivity
的交易中收到虚假结果,因为它与MainActivity
分开,如果是,我该怎么办呢?
(2)你认为我应该将1200行代码粘贴到doInBackground
中,从而产生一个2200行的怪物,所以我不必担心并发吗?
(3)也许从与UI分离的线程中启动{{1}}? (不知道如何控制,但我愿意尝试。)
(4)你还有什么建议?