【发布时间】:2021-06-26 01:54:46
【问题描述】:
我使用 Android 架构组件(ViewModel、LiveData)并使用 Room 通过 Repository 从本地 Sqlite 数据库中获取数据。最外层的观察者就好了,问题只出在内部的观察者身上。
查看代码:
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
BranchDetailsViewModel branchDetailsViewModel = new BranchDetailsViewModel(application);
Observer<Bank> bankObserver = new Observer<Bank>() {
@Override
public void onChanged(Bank bank) {
if(bank!= null)
binding.tvBank.setText(bank.getBank());
}
};
branchDetailsViewModel.getBranchById(branchIid).observe(this, new Observer<Branch>() {
@Override
public void onChanged(Branch branch) {
branchDetailsViewModel.getBankById(branch.getBankId()).observe(getViewLifecycleOwner(), bankObserver);
branchDetailsViewModel.getCityById(branch.getCityId()).observe(requireActivity(), new Observer<City>() {
@Override
public void onChanged(City city) {
if(city != null)
binding.tvCity.setText(city.getCity() + " cty");
}
});
branchDetailsViewModel.getDistrictById(branch.getDistrictId()).observe(requireActivity(), new Observer<District>() {
@Override
public void onChanged(District district) {
if(district != null)
binding.tvDistrict.setText(district.getDistrict());
}
});
branchDetailsViewModel.getStateById(branch.getStateId()).observe(requireActivity(), new Observer<State>() {
@Override
public void onChanged(State state) {
if(state!= null)
binding.tvState.setText(state.getState());
}
});
}
});
}
我使用命名和匿名观察者都试过了。我不明白这里有什么问题。
有时它会抛出 NullPointerExceptions。有时无法更改语言环境。
04-09 15:48:45.182 2096-2113/com.appsbharti.bharatbankdetails E/SQLiteDatabase: Failed to open database '/data/data/com.appsbharti.bharatbankdetails/databases/bank_details.db'.
android.database.sqlite.SQLiteException: Failed to change locale for db '/data/data/com.appsbharti.bharatbankdetails/databases/bank_details.db' to 'en_IN'.
at android.database.sqlite.SQLiteConnection.setLocaleFromConfiguration(SQLiteConnection.java:386)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:218)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:804)
at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:92)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:53)
at androidx.room.SQLiteCopyOpenHelper.getWritableDatabase(SQLiteCopyOpenHelper.java:90)
at androidx.room.RoomDatabase.inTransaction(RoomDatabase.java:476)
at androidx.room.RoomDatabase.assertNotSuspendingTransaction(RoomDatabase.java:281)
at com.appsbharti.bharatbankdetails.Daos.HistoryDao_Impl.insert(HistoryDao_Impl.java:45)
at com.appsbharti.bharatbankdetails.Repositories.HistoryRepository$1.run(HistoryRepository.java:37)
at androidx.room.TransactionExecutor$1.run(TransactionExecutor.java:45)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
Caused by: android.database.sqlite.SQLiteDiskIOException: disk I/O error (code 1802)
at android.database.sqlite.SQLiteConnection.nativeExecute(Native Method)
at android.database.sqlite.SQLiteConnection.execute(SQLiteConnection.java:548)
at android.database.sqlite.SQLiteConnection.setLocaleFromConfiguration(SQLiteConnection.java:364)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:218)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:804)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:789)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:804)
at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:92)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:53)
at androidx.room.SQLiteCopyOpenHelper.getWritableDatabase(SQLiteCopyOpenHelper.java:90)
at androidx.room.RoomDatabase.inTransaction(RoomDatabase.java:476)
at androidx.room.RoomDatabase.assertNotSuspendingTransaction(RoomDatabase.java:281)
at com.appsbharti.bharatbankdetails.Daos.HistoryDao_Impl.insert(HistoryDao_Impl.java:45)
at com.appsbharti.bharatbankdetails.Repositories.HistoryRepository$1.run(HistoryRepository.java:37)
at androidx.room.TransactionExecutor$1.run(TransactionExecutor.java:45)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
还有一个问题是我不确定我应该在 Fragment 中使用哪个作为 Observer 的所有者,requireActivity() 或 getActivity()(我收到警告说这可能返回 null,所以我没有使用它)或 @987654326 @(获取片段的生命周期所有者对象)。
【问题讨论】:
-
真正的问题是什么?如果你在每个“onChanged()”方法上放置断点,它会被触发吗?或者您仅通过查看您的用户界面(binding.tvCity、binding.tvState 等...)就发现某些东西无法正常工作?
-
实际上我通过创建自定义 POJO 并在 sql 中运行长查询以一次发送所有数据来找出解决方案。这个问题的主要问题仍然是我如何确保所有这些内部观察者在父观察者不返回某些东西之前不会运行。 (我相信你知道他们第一次总是返回 null )。我们如何链接观察者,以便一个在另一个获取值之后运行。这个问题对我来说还是很重要的。
-
它没有回答我的问题;)我多次使用嵌套的“observe()”调用,没有任何问题。在您的情况下,有 LiveData、LifecycleOwner 和 ViewModel 可能是问题所在。因此,如果您将断点放在每个“onChanged()”级别,那么您就可以理解真正的工作流程。另外:我们看不到任何“LiveData.postValue()”,因此更难为您提供帮助。
-
我遵循 Android 架构。我还听说 RxJava 相当不错。实际上这个应用程序很简单,我不想添加第三方库。我使用了从资产创建的预填充数据库。几乎有 0 个插入。我还搜索了是否可以使用 Room 进行任何只读数据库访问,但一无所获。我个人认为 SqliteHelper 比 ROOM 更好。
-
如果你了解 Android 架构组件和 ROOM 库,我请求你看看我的另一个问题,如果你有足够的时间。感谢 sql joins,我幸运地解决了这个问题,但解决这个问题很棘手。由于未知原因,它给了我 FOREIGN KEY CONSTRAINT 错误。它也是同一个项目的一部分。 stackoverflow.com/questions/66965010/…
标签: android observable android-livedata observer-pattern