一个场景:定时处理一些数据,这个过程需要较长时间,而且app未必会是前端进程。如何来实现这样的功能?
Receiver接收广播的回调是在主线程中实现的,当广播所驱动的行为耗时的话,可能会引起ANR。
这样就有必要创建工作线程,后台任务放在工作线程上实现。
/*******************
什么是ANR
Android Not Response
什么时候发生?
. 5s内,对用户的输入操作没有反应。
. 10s内,BroadcastReceiver没有执行完毕
********************/
简单创建Worker Thread是不可行的,这是因为当四大组件都不存在的话,进程是容易被回收的,Receiver是worker thread的执行是并行的,Receiver执行完毕之后,可能被回收。这样就不能保证工作线程正常执行。
正确的方向是Receiver启动一个后台的Service(一般是IntentService),来执行后台任务。
这样正确了吧?
还是不完全,后台任务耗时的话,cpu是会进入休眠状态的,以保持电量。所以,开发者需要手动设置wakeLock,以保持cpu在后台任务执行完毕之后释放wakelock,才进入休眠。
Android针对这种场景封装了sdk接口WakefulBroadcastReceiver,
receiver的子类,接收到广播后需要创建IntentService,IntentService执行完毕之后需要释放wake lock。
public class MyWakefulReceiver extends WakefulBroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // Start the service, keeping the device awake while the service is // launching. This is the Intent to deliver to the service. Intent service = new Intent(context, MyIntentService.class); startWakefulService(context, service); } }
public class MyIntentService extends IntentService { public static final int NOTIFICATION_ID = 1; private NotificationManager mNotificationManager; NotificationCompat.Builder builder; public MyIntentService() { super("MyIntentService"); } @Override protected void onHandleIntent(Intent intent) { Bundle extras = intent.getExtras(); // Do the work that requires your app to keep the CPU running. // ... // Release the wake lock provided by the WakefulBroadcastReceiver. MyWakefulReceiver.completeWakefulIntent(intent); } }
其实还是封装的不太好,completeWakefulIntent 函数如果不需要开发者调用,那会更好,其实也很容易实现 (^ - ^)