【问题标题】:Right way to use Android BroadcastReceiver to trigger Room DB Operation使用Android BroadcastReceiver触发Room DB Operation的正确方法
【发布时间】:2018-06-14 06:25:10
【问题描述】:

我的应用程序有一个前台服务,我希望我的所有网络调用都发生在其中,以保持事情正常。我还在 Service 中实现了 Room 数据库。

我的计划是在服务端基于触发器进行所有数据库操作。广播在 Intent 中以 Bundle 的形式将数据传递给服务。

但是,我的问题是:

  1. BroadcastListeners 在主线程上运行。
  2. Room DB 操作需要脱离主线程,这样应用才不会 ANR'd
  3. 当我在 BroadcastListener 中实现 HandlerThread 或具有 Runnable 的线程时,我无法传递数据,因为意图变量是“从内部类访问的,需要声明为 final

我的代码(就目前而言)如下。

BroadcastReceiver houseCallCancelReceiver = new BroadcastReceiver () {
        @Override
        public void onReceive(Context context, Intent intent) {
            new Thread(new Runnable()  {
                @Override
                public void run() {
                    Bundle bundle = intent.getParcelableExtra ("housecall");
                    String email = bundle.getString("email");
                    String housecallid = bundle.getString("housecallid");
                    .
                    .
                    .
                    }
                }
            }).start();
        }
    }; 

ATM 我能想到几个选项,包括:

  1. 在函数中编写 DB 逻辑(和线程)并传递 意图作为线程的参数。 - 这导致代码是 不是全部在一起,而且更难阅读,因为我会有一个 每个操作的功能
  2. 在 AsyncTask 中进行调用 - 与上述相同,外加大量一次性 AsyncTask 调用。另外,我可以在 ForegroundService 中调用 AsyncTask 吗?
  3. 升级到 Java 1.8 并使用 Lambda - 我担心这可能会破坏与旧手机的兼容性。

非常感谢任何帮助!

【问题讨论】:

    标签: android multithreading android-room


    【解决方案1】:

    我在这个帖子中找到了一个答案(各种):Runnable with a Parameter

    通过将 Room DB 逻辑移动到一个单独的函数中,并在函数本身中声明一个类并在构造函数中调用该函数,我可以将 Intent 作为参数传递给该类。

    BroadcastReceiver refreshHousecallsReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                Log.d(TAG, "onReceive: In refreshHousecallsReceiver");
                class OneShotTask implements Runnable {
                    // idea from https://stackoverflow.com/questions/5853167/runnable-with-a-parameter
                    Intent intent;
                    OneShotTask(Intent intent1) { intent= intent1; }
                    public void run() {
                        refreshHouseCalls(intent);
                    }
                }
                Thread t = new Thread(new OneShotTask(intent));
                t.start();
            }
        };
    

    我试过了,效果很好。但是,这不是一种可重复使用的做事方式,我正在寻找其他方法来做同样的事情 - 请也分享您的示例或想法!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-13
      • 1970-01-01
      相关资源
      最近更新 更多