使用 Android BroadcastReceiver 触发 Room DB 操作的正确方法
Right way to use Android BroadcastReceiver to trigger Room DB Operation
我的应用程序有一个前台服务,我希望我的所有网络调用都发生在前台服务中,以保持一切正常。我还在服务中实现了一个房间数据库。
我的计划是让所有数据库操作都基于触发器在服务端进行。广播在 Intent 中以 Bundle 的形式将数据传递给服务。
但是,我的问题是:
- BroadcastListeners 在主线程上运行。
- Room DB 操作需要脱离主线程,这样应用才不会出现 ANR
- 当我在 BroadcastListener 中实现 HandlerThread 或带有 Runnable 的线程时,我无法传递数据,因为意图变量是'从内部 class 访问的并且需要宣布最终'
我的代码(目前)如下。
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我能想到几个方案,包括:
- 在函数中编写数据库逻辑(和线程)并传递
意图作为线程的参数。 - 这导致代码是
不是全部放在一起,这样更难阅读,因为我会有一个
每个操作的功能
- 在 AsyncTask 中进行调用 - 与上面相同加上大量一次性 AsyncTask 调用。另外,我可以在 ForegroundService 中调用 AsyncTask 吗?
- 升级到 Java 1.8 并使用 Lambdas - 我担心这可能会破坏与旧手机的兼容性。
非常感谢任何帮助!
我在这个帖子中找到了(某种程度上的)答案:Runnable with a Parameter
通过将 Room DB 逻辑移动到一个单独的函数,并在函数本身中声明一个 class 并在构造函数中调用该函数,我可以将 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
Intent intent;
OneShotTask(Intent intent1) { intent= intent1; }
public void run() {
refreshHouseCalls(intent);
}
}
Thread t = new Thread(new OneShotTask(intent));
t.start();
}
};
我试过了,很管用。但是,这不是一种可重复使用的做事方式,我正在寻找其他做同样事情的方式 - 请分享您的示例或想法!
我的应用程序有一个前台服务,我希望我的所有网络调用都发生在前台服务中,以保持一切正常。我还在服务中实现了一个房间数据库。
我的计划是让所有数据库操作都基于触发器在服务端进行。广播在 Intent 中以 Bundle 的形式将数据传递给服务。
但是,我的问题是:
- BroadcastListeners 在主线程上运行。
- Room DB 操作需要脱离主线程,这样应用才不会出现 ANR
- 当我在 BroadcastListener 中实现 HandlerThread 或带有 Runnable 的线程时,我无法传递数据,因为意图变量是'从内部 class 访问的并且需要宣布最终'
我的代码(目前)如下。
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我能想到几个方案,包括:
- 在函数中编写数据库逻辑(和线程)并传递 意图作为线程的参数。 - 这导致代码是 不是全部放在一起,这样更难阅读,因为我会有一个 每个操作的功能
- 在 AsyncTask 中进行调用 - 与上面相同加上大量一次性 AsyncTask 调用。另外,我可以在 ForegroundService 中调用 AsyncTask 吗?
- 升级到 Java 1.8 并使用 Lambdas - 我担心这可能会破坏与旧手机的兼容性。
非常感谢任何帮助!
我在这个帖子中找到了(某种程度上的)答案:Runnable with a Parameter
通过将 Room DB 逻辑移动到一个单独的函数,并在函数本身中声明一个 class 并在构造函数中调用该函数,我可以将 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
Intent intent;
OneShotTask(Intent intent1) { intent= intent1; }
public void run() {
refreshHouseCalls(intent);
}
}
Thread t = new Thread(new OneShotTask(intent));
t.start();
}
};
我试过了,很管用。但是,这不是一种可重复使用的做事方式,我正在寻找其他做同样事情的方式 - 请分享您的示例或想法!