Android Studio - 线程完成后从 SQLite 获取数据
Posted
技术标签:
【中文标题】Android Studio - 线程完成后从 SQLite 获取数据【英文标题】:Android Studio - get data from SQLite after thread done 【发布时间】:2021-12-01 18:56:18 【问题描述】:在启动应用程序时,我首先需要同步数据库中的数据,以便用户可以离线查看数据。因此,我创建了一个特殊的同步类,用于比较来自网络的数据,并在必要时将其写入本地 SQLite 数据库。
从 SQLite 数据库中检索数据以将更改与来自 Internet 的数据进行比较时会出现问题。
我尝试使用通常在其他类中使用的 AsyncTask,但这会导致应用程序一遍又一遍地重新启动。
当使用“public class GetDbData implements Runnable ...”时,会出现以下错误,我不清楚是什么原因造成的。
感谢您的回复。
错误信息:
2021-10-13 11:01:36.682 18498-18590/com.commonsware.android E/AndroidRuntime: FATAL EXCEPTION: Thread-10
Process: com.commonsware.android, PID: 18498
java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.
at androidx.room.RoomOpenHelper.checkIdentity(RoomOpenHelper.java:136)
at androidx.room.RoomOpenHelper.onOpen(RoomOpenHelper.java:116)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onOpen(FrameworkSQLiteOpenHelper.java:151)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:409)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:298)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:96)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:54)
at androidx.room.RoomDatabase.query(RoomDatabase.java:238)
at com.commonsware.android.database.DbDao_Impl.getAllNews(DbDao_Impl.java:190)
at com.commonsware.android.synchronize_data.SyncNews$GetDbData.run(SyncNews.java:178)
at java.lang.Thread.run(Thread.java:764)
2021-10-13 11:01:36.869 18498-18498/com.commonsware.android E/WindowManager: android.view.WindowLeaked: Activity com.commonsware.android.SyncActivity has leaked window DecorView@30e5ecf[SyncActivity] that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:529)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:346)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
at android.app.Dialog.show(Dialog.java:329)
at com.commonsware.android.SyncActivity.onCreate(SyncActivity.java:24)
at android.app.Activity.performCreate(Activity.java:7148)
at android.app.Activity.performCreate(Activity.java:7139)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2924)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3079)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1836)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6702)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911)
我的班级:
public class SyncNews
private Context context;
private DbRoomDatabase db;
private DbDao dbDao;
private String JSON_URL_NEWS = "URL for data";
private Boolean webDataError = false;
private JSONObject webData;
private List<News> newsDB = null;
private List<News> newsListAdd = new ArrayList<>();
private List insertData;
public SyncNews(Context ct)
context = ct;
db = DbRoomDatabase.getDatabase(context);
dbDao = db.dbDao();
GetWebData getWebData = new GetWebData();
Thread getWebDataThread = new Thread(getWebData);
getWebDataThread.start();
while(webDataError == false && getWebDataThread.isAlive()) ;
if(webDataError == false)
GetDbData getDbData = new GetDbData();
Thread getDbDataThread = new Thread(getDbData);
getDbDataThread.start();
while(getDbDataThread.isAlive())
Log.d("TEST", String.valueOf(newsDB));
public void syncWithDb()
//synchronize
public void InsertData ()
if (insertData.size() > 0)
dbDao.insertMultipleNews(insertData);
public class GetWebData implements Runnable
@Override
public void run()
if(!this.getWebData())
Looper.prepare();
webDataError = true;
Toast.makeText(context, context.getString(R.string.mess_data_has_not_been_synchronized), Toast.LENGTH_LONG).show();
Looper.loop();
public Boolean getWebData()
RequestQueue requestQueue = Volley.newRequestQueue(context);
RequestFuture<JSONObject> future = RequestFuture.newFuture();
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, JSON_URL_NEWS, new JSONObject(), future, future);
requestQueue.add(request);
try
webData = future.get();
Log.e("getWebData", String.valueOf(request));
catch (InterruptedException | ExecutionException e)
if (VolleyError.class.isAssignableFrom(e.getCause().getClass()))
VolleyError ve = (VolleyError) e.getCause();
Log.i("getWebData", String.valueOf(ve));
if (ve.networkResponse != null)
Log.i("getWebData", String.valueOf(ve.networkResponse));
Log.i("getWebData", String.valueOf(ve.networkResponse.statusCode));
Log.i("getWebData", String.valueOf(ve.networkResponse.data));
return false;
return true;
public class GetDbData implements Runnable
@Override
public void run()
newsDB = dbDao.getAllNews();
【问题讨论】:
【参考方案1】:每次更改数据库的架构/实体类时,您可能需要升级数据库版本
在这种情况下,您似乎需要升级您的数据库版本,您可以在您的数据库类中的@Database(version = xx)
中找到
【讨论】:
感谢您的回复,一般都是通过卸载重装app来解决的。我更担心第二条消息,我只是不知道它是否相关,所以我把它写下来。有趣的是,它在模拟器中运行没有任何问题,但是当我在手机上尝试它时,它会出现 FATAL ERROR。 似乎不能依靠重新安装解决方案。关于第二个日志,您似乎需要检查代码实现是否意外将主上下文(活动/片段)传递给您的 DB 类,您应该使用应用程序上下文而不是 DB 类 在活动中我只将这个类称为线程,但有可能你是对的。new Thread() @Override public void run() try new SyncNews(getApplicationContext()); catch (Exception e) finally dialog.dismiss(); .start();
我终于找到了解决方案。只需将 fallbackToDestructiveMigration() 与 Room.databaseBuilder 一起使用。
fallbackToDestructiveMigration()
不适合在生产代码中使用,一旦您更改数据库架构,它将删除整个数据库。当您更改生产代码的架构时,您应该添加迁移。以上是关于Android Studio - 线程完成后从 SQLite 获取数据的主要内容,如果未能解决你的问题,请参考以下文章