在 Adroid 中,我使用 Retrofit2 调用我的服务器来获取数据。
在 onResponse 检查数据库中的版本后,我正在删除并重新创建数据库中的表,然后插入数据。一切正常,数据填写正确,但每次我在控制台中都会收到警告。
这是我的代码的一部分:
@Override
public void onResponse(@NonNull Call<List<Movie>> call, @NonNull Response<List<Movie>> response) {
movieList = response.body();
myDb = new DatabaseHelper(getApplicationContext());
if (movieList != null) {
if (response.isSuccessful() && movieList.size() > 0) {int liveVersion = 0;
liveVersion = Integer.parseInt(movieList.get(0).getVersiondb());
if (liveVersion>version || version==0) { myDb.clearTable();
for (int i = 0; i < movieList.size(); i++) {
myDb.insertData(movieList.get(i).getKateg(),movieList.get(i).getFullname(), movieList.get(i).getVersiondb());
}
}
} }
}
void clearTable() {
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
db.execSQL("CREATE TABLE " + TABLE_NAME + "(ID INTEGER PRIMARY KEY AUTOINCREMENT, KATEG TEXT, FULLNAME TEXT, VERSION TEXT)");
db.close();
}
void insertData(String kateg, String fullname, String version) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COL_2,kateg);
contentValues.put(COL_3,fullname);
contentValues.put(COL_4,version);
db.insert(TABLE_NAME,null,contentValues);db.close();
}
警告说:
(当前消息:持续时间=5005ms seq=39 h=android.os.Handler c=retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1$$ExternalSyntheticLambda0)
MIUIScout 应用 myapp.com W 事件:APP_SCOUT_HANG 线程:主回溯:
在 java.lang.String.charAt(本机方法)
在 java.lang.String.equals(String.java:1271)
在 android.database.DatabaseUtils.getSqlStatementType(DatabaseUtils.java:1574)
在 android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:1050)
在 android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:654)
在 android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:590)
在 android.database.sqlite.SQLiteProgram.(SQLiteProgram.java:62)
在 android.database.sqlite.SQLiteStatement。(SQLiteStatement.java:34)
在 android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1700)
在 android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1571)
在 my.app.DatabaseHelper.insertData(DatabaseHelper.java:99)
在 my.app.StartActivity$1.onResponse(StartActivity.java:84)
在retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1.lambda$onResponse$0$retrofit2-DefaultCallAdapterFactory$ExecutorCallbackCall$1(DefaultCallAdapterFactory.java:89)
在retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1$$ExternalSyntheticLambda0.run(来源未知:6)
在 android.os.Handler.handleCallback(Handler.java:938)
在 android.os.Handler.dispatchMessage(Handler.java:99)
在 android.os.Looper.loopOnce(Looper.java:210)
在 android.os.Looper.loop(Looper.java:299)
在 android.app.ActivityThread.main(ActivityThread.java:8319)
在 java.lang.reflect.Method.invoke(本机方法)
在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556)
在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1038)
在我加粗的一行中,它指向
insertData
方法,但是,由于它毫无问题地插入了所有内容,我不确定出了什么问题。
我认为这可能与
db.close()
有关,因为我在循环中每次插入后都会关闭数据库。
我删除了
db.close()
,现在警告消失了。
该警告似乎是由于主线程延迟过多所致。关闭数据库然后重新打开数据库相对来说比较消耗资源。
此外,像每次插入一样,执行许多单个事务本身也是高效的。
您不仅不应该关闭并重新打开数据库,而且您也许应该考虑在单个事务中执行循环中的所有插入。
也许考虑以下内容(即松散地基于您的代码)
为了方便不获取数据库实例,两个版本的
insertData
方法:-
void insertData(SQLiteDatabase db, String kateg, String fullname, String version) {
if (db == null) db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COL_2, kateg);
contentValues.put(COL_3, fullname);
contentValues.put(COL_4, version);
db.insert(TABLE_NAME, null, contentValues);
}
void insertData(String kateg, String fullname, String version) {
insertData(null, kateg, fullname, version);
}
insertData
方法,并将 SQLiteDatabase 设置为 null(因此会获取 SQLiteDatabase)。不使用
clearTable
方法,因为删除行可能更有效(无论如何删除表都必须这样做)。相反,删除嵌入在建议的 insertAfterClearIfApplicable
方法中(显然可以更改方法名称以适应)
代码:-
void insertAfterClearIfApplicable(List<Movie> movieList, int liveVersion) {
if (movieList == null || movieList.size() < 1) return; /* nothing to do so return */
SQLiteDatabase db = this.getWritableDatabase(); /* get the SQLiteDatabase */
db.beginTransaction(); /* Start a transaction */
boolean allDoneOk = true; /*<<<<<<<<<< set to false if the transaction should be rolled back */
if (movieList.size() > 0) {
/* Handle the first element i.e. whether or not to delete all rows from the table */
int version = Integer.parseInt(movieList.get(0).getVersion());
if (liveVersion > version || version == 0) {
/* might as well use delete instead of drop as drop has to delete all rows anyway
* and saves a little by not having to then create the table again */
db.delete(TABLE_NAME, null, null);
}
/* Insert all of the rows to be added */
for (Movie m : movieList) {
insertData(db, m.getKateg(), m.getFullName(), m.getVersion());
}
/* unless otherwise flagged set the transaction to NOT rollback */
/* note if not set as successful then ALL database actions will be rolled back */
if (allDoneOk) db.setTransactionSuccessful();
/* end the transaction will commit/write all the actions to the database (if set as susccessful) in a single go
thus reducing the overheads */
db.endTransaction();
}
}
List<Movie>
而不是响应主体,因此应相应地进行调整/更改。