-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathback.html
More file actions
73 lines (73 loc) · 6.29 KB
/
back.html
File metadata and controls
73 lines (73 loc) · 6.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Rock with Android</title>
<link rel="shortcut icon" href="img/favicon.ico">
<link href="css/main.css" type="text/css" rel="stylesheet">
</head>
<body>
<div class="wrapper">
<div class="container">
<h1>Rock with Android</h1>
<hr>
<div class="mod">
<h3>Service和BroadcastReceiver</h3>
<p>安卓本身是一个多任务的系统,所以可以有真正的后台服务存在。<a target="_blank" href="http://developer.android.com/reference/android/app/Service.html">Service</a>就是对应的封装类。</p>
<p>在实际中,典型的后台服务需求有播放,推送/同步数据,定时任务这些类型。前两者是使用典型的C/S结果的场景,而后者其实在安卓上面可以使用Alarm的机制来做到比较轻的方案,不用后台常驻一个服务。</p>
<p>如果希望服务是单独开一个进程的话,需要在manifest里使用下面的声明,":remote"标识该进程的名字,确切的讲是冒号后面是进程的名字。单独使用进程的好处是彻底和UI进程分开,但是也会有麻烦的地方,比如通讯是跨进程的,需要走AIDL接口,或者使用BroadcastReceiver监听广播,而且传输的数据大小也不能太大。所以除非有额外的好处,并不推荐单独起进程。</p>
<pre class="code">
<service android:name=".app.SyncService" android:process=":remote" />
</pre>
<p>不单独开进程的话,Service本身默认也是在主线程里的,所以如果有耗时的计算或者IO操作,还是需要自己起线程或者使用AsyncTask来异步处理。</p>
<p>具体的例子可以参考<a target="_blank" href="http://developer.android.com/reference/android/app/Service.html">Service</a>的Local Service Sample部分。使用IBinder得到Service的Client,直接调用对应的接口,这样效率比较高。但是由于上面所说的异步处理的问题,所以直接调用Service的接口都是阻塞的,适用于返回结果的情况。</p>
<p>所以如果Service里面的操作比较耗时的话,就需要利用异步加回调的机制和Client通信。具体做法可以是下面的方法:</p>
<ol>
<li>Client调用Service接口,直接返回,然后Client起BroadcastReceiver,等Service异步操作完,发广播得到结果。</li>
<li>Client和Service都使用BroadcastReceiver,使用广播互发消息。<span class="tip">这个方案因为都是使用广播,会增大延时,并且Intent本身数据有大小限制,太大的数据没法直接传递。</span></li>
</ol>
<h4>BroadcastReceiver</h4>
<p><a target="_blank" href="http://developer.android.com/reference/android/content/BroadcastReceiver.html">BroadcastReceiver</a>可以在manifest里面声明,也可以在代码里直接使用 Context.registerReceiver()动态注册。典型的使用可以是Activity和Service通讯,也可以是Activity间互相通讯,还可以是不同应用间通讯。因为使用方便和灵活,容易被滥用。</p>
<ol>
<li>在Activity中,如果在onResume中注册,那么需要在onPause里注销,减少系统开销。</li>
<li>如果在onReceive里的操作比较耗时,或者希望Receiver的有更长的生命周期,需要和Service一起配合使用。</li>
</ol>
<p>在安卓的support包里,新加入了<a target="_blank" href="http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html">LocalBroadcastManager</a>,对于应用内部需要使用广播的情况更加友好和高效了。</p>
<p>LocalBroadcastManager所发的广播,并且注册的Receiver的监听,都只是针对当前应用,所以从安全和性能都比全局的Receiver和广播要高的多。具体使用如下:</p>
<pre class="code">
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(context);
manager.registerReceiver(receiver, filter);
manager.sendBroadcast(intent);
//如果有对应的Receiver相当于直接调用其onReceiver,所以会阻塞直到处理完成才返回
manager.sendBroadcastSync(intent);
manager.unregisterReceiver(receiver);
</pre>
<h4>IntentService</h4>
<p><a target="_blank" href="http://developer.android.com/reference/android/app/IntentService.html">IntentService</a>有点类似AsyncTask,也是运行在独立线程里,不会阻塞UI线程,可以看成是一种轻量级的Service。通过调用startService(Intent) 来调用IntentService,在onHandleIntent(Intent)里面处理对应Intent,执行操作。</p>
<ol>
<li>和Service不同的地方是,IntentService是需要时启动,处理完成后就退出的,并不真正后台长期存在</li>
<li>IntentService同时只能处理一个请求,也就是说只会起一个工作线程</li>
<li>IntentService适用于业务简单的后台单次或者重复性任务,Client只是调用,不需要等待结果的情况</li>
</ol>
<h4>AlarmManager</h4>
<p><a target="_blank" href="http://developer.android.com/reference/android/app/AlarmManager.html">AlarmManager</a>提供了系统闹钟服务的接口,利用闹钟服务,可以达到Cron的效果。一般可以和IntentService搭配使用,比如定时后台同步数据,定时清理临时文件等操作。</p>
<pre class="code">
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, SyncService.class);
PendingIntent pIntent = PendingIntent.getService(context,
0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + 2*60*1000, 2*60*1000, pIntent);
</pre>
<p><a href="index.html">目录</a>|<a href="intent.html">上一章</a>|<a href="screen.html">适配</a></p>
</div>
</div>
<div class="wrapper-footer"></div>
</div>
<div class="footer">
<div class="container">
<a href="https://github.com/beartung/rockwithandroid">RockWithAndroid</a> by <a href="http://github.com/beartung">@Bear</a>
</div>
</div>
</body>
</html>