当前位置: 首页 > 知识库问答 >
问题:

我可以在Observer中添加Observer吗?我确实试过了,但没有正常工作。有时其中一人工作,有时无人工作

邹海超
2023-03-14

我使用Android架构组件(ViewModel,LiveData),并使用Room从使用存储库的本地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) 

还有一个问题是,我不确定应该在片段中使用哪一个作为观察者的所有者,requireActivity()getActivity()(我收到警告,这可能会返回null,所以我没有使用它)或getViewLifecycleOwner()(获取片段的生命周期所有者对象)。

共有3个答案

澹台浩广
2023-03-14
  1. 请使用YouFragmentClassName。此或视图生命周期所有者
公子昂
2023-03-14

实际上,viewlifecycleOwnerthis是可以接受的。你必须调用你的fragment。这个

我看到你没有调用任何函数来更新内部的LiveData值。您不应该包装嵌套的观察者,因为内部观察者将被调用多次,与外部观察者的调用次数相对应。

您只需要调用更新LiveData值的函数就可以触发内部观察者的onChanged回调

请阅读本文以避免多次使用数据https://medium.com/androiddevelopers/livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case-ac2622673150

李宜然
2023-03-14

如果您在一个片段中,您不能通过this来观察,您应该通过viewlifececleOwner。在您的情况下,您正在设置一个观察来从房间中获取分支的值,然后根据分支的不同,您的其他观察者将被调用

这意味着您的内部观察者将在调用分支观察者之后进行观察。

当您将观察者绑定到片段的生命周期时,观察者按照片段本身的生命周期工作。

将它绑定到生命周期所有者应该可以工作,主要是因为this在片段的情况下不起作用。

 类似资料:
  • 我试图用一个服务人员使用Workbox制作一个非常基本的PWA,但是我有一个问题。我正在使用命令行界面来生成服务工作人员,一切正常,完美的亮点,但我不能将我的index.html添加到运行时缓存中。我必须将其添加到全局模式,以便我的网站在离线模式下工作,但当我更新index.html文件时,除非我清除缓存,否则不会更新。我想要和我的js和css一样的东西。当我升级这些文件时,它们会更新。这是我的工

  • 我在演示应用程序中使用android导航组件。我有一个非常简单的案例。一个活动,两个片段,A和B。我在谷歌的示例应用程序中设置了导航控件。当我试图使用简单的onClickListener打开片段B时,如下所示: 一切正常。B片段打开,点击后退按钮弹出。但当我试图从LiveData observer中使用它时,就像这样: 片段B打开,但通过点击后退按钮应用程序崩溃,错误导航目标com.myapp:

  • 我有一个错误,现在在生产中出现了两次,其中一个分叉/连接池停止工作,尽管它有工作要做并且正在添加更多工作。 这是我到目前为止得出的结论,以解释为什么要执行的任务队列被填满并且任务结果流停止。我有线程转储,其中我的任务生产者线程正在等待fork/连接提交完成,但是没有ForkJoinpool工作线程对此做任何事情。 不管我在做什么,这都不应该发生,对吗?线程转储来自检测到初始条件后的许多小时。我还有

  • 问题内容: 在担任前端开发人员的头几个月后,我才开始涉足后端开发。我正在使用postgreSQL,似乎无法将我的头放在nextval()函数周围。我读了这篇,但对我来说还不清楚。 http://www.postgresql.org/docs/current/interactive/functions- sequence.html nexval()有什么好处/用例? 问题答案: 是从序列中获取下一个

  • 问题内容: 我试过在Windows 7上安装docker(使用boot2docker)。但是控制台只是突然存在,我看不到错误,更不用说运行任何命令了。 在安装过程中,我尝试安装和不安装VirtualBox。我也尝试卸载并重新安装docker和virtualbox。似乎没有任何作用。 这是我运行时看到的控制台错误: 问题答案: 请检查您的BIOS的VT-x设置。根据您提供的日志,有一个错误: