第一行代码笔记4:服务

来源:互联网 发布:监控录像恢复软件 编辑:程序博客网 时间:2024/06/06 20:17
一、服务

适用场景:非常适合执行那些不需要和用户交互而且长期运行的任务。

注意点:1)服务并不是运行在一个独立的进程当中,而是依赖于创建服务时所在的应用程序进程。当某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行。

2)服务并不会自动开启线程,所有代码都默认运行在主线程当中。

二、解析异步消息处理机制

Android中的异步消息处理主要有四个部分组成:Message、Handler、MessageQueue和Looper。

1、Message:是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程间交换信息。

2、Handler:可用来处理消息(发送和处理)。

3、MessageQueue:主要用于存放所有通过Handler发送的消息。这部分消息会一直存在于消息队列中,等待被处理。每个线程中只会有一个MessageQueue对象。

4、Looper:是每个线程中的MessageQueue的管家,调用Looper的loop()后,就会进入到一个无限循环当中,然后每当发现MessageQueue中存在一条消息,就会将它取出,并传递到Handler的handleMessage()中。每个线程中只会有一个Looper对象。

三、AsyncTask

1、参数介绍。1)Params:执行AsyncTask时需传入的参数,可在后台任务中执行。2)Progress:后台任务执行时,需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。3)Result:当任务执行完毕,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。

2、方法介绍

1)onPreExecute():在后台任务开始执行之前调用,用于进行一些界面上的初始化操作,比如显示一个进度对话框等。

2)doInBackground(Params…):子线程中执行,如果AsyncTask第三个泛型参数指定的是Void,就可以不返回任务执行结果。如果需要更新UI元素,比如反馈当前任务的执行进度,可以调用publishProgress(Progress…)来完成。

3)onProgressUpdate(Progress…):当后台执行了publishProgress(Progress…)后,这个方法很快会被调用,方法中携带的参数是后台任务中传递过来的。这个方法中可以对UI进行操作,利用参数中的数值就可对界面元素进行相应更新。

4)onPostExecute(Result):当后台任务执行完成并通过return返回时,这个方法很快会被调用。可进行一些UI操作。

三、服务的基本用法

1、需要在清单文件中注册(四大组件都需注册)。

2、方法介绍

1)onBind():

2)onCreate():在服务第一次创建时调用。

3)onStartCommand():在每次服务启动时调用。

4)onDestroy():在服务销毁时调用。

3、启动和停止服务

Intent startIntent = new Intent(this, MyService.class);startService(startIntent); // 启动服务
Intent stopIntent = new Intent(this, MyService.class);stopService(stopIntent); // 停止服务
上面服务的停止是由活动来决定的,如何让服务自己停止呢?只需在服务中调用stopSelf()即可。

4、活动和服务相互通信

1)活动->服务

上述启动服务的方法,在服务启动后,活动与服务基本没关系了。通过onBind(),活动可以指挥服务。

步骤一:服务中定义一个Binder类和对象,在onBind()中返回该Binder对象。

步骤二:活动中取得该Binder对象,就可通过该Binder对象控制服务。

private MyService.DownloadBinder downloadBinder;private ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {downloadBinder = (MyService.DownloadBinder) service;downloadBinder.startDownload();downloadBinder.getProgress();}};

步骤三:记得绑定服务和解绑服务

Intent bindIntent = new Intent(this, MyService.class);bindService(bindIntent, connection, BIND_AUTO_CREATE); // 绑定服务
第一个参数是intent对象;第二个参数是ServiceConnection实例;第三个参数是一个标志位,这里传入BIND_AUTO_CREATE表示在活动和服务绑定后自动创建服务。这会使得服务中的onCreate()执行,按onStartCommand()不会执行。
unbindService(connection); // 解绑服务

解绑服务后,会执行服务的onDestroy()。

2)服务和活动怎么通信呢?

如果通过bindService(),在服务中可通过回调方法来通知活动。

通过广播向活动发送消息。

四、服务的生命周期

onCreate()、onStartCommand()、onBind()、onDestroy()。

虽然每次调用startService(),onStartCommand()就会执行一次,但实际上每个服务都只会存在一个实例。所以不管调用多少次startService(),只需调用一次stopService()或stopSelf(),服务就会停止。
如果对一个服务既调用了startService()又调用了bindService(),此时该如何销毁服务呢?根据Android的机制,一个服务只要被启动或被绑定后,就会一直处于运行状态,必须让两个条件都不满足,服务才能被销毁。所以,要同时调用stopService()和unbindService(),onDestroy()才会被执行。

五、服务的高级技巧

1、使用前台服务

需求:服务的系统优先级比较低,当系统出现内存不足时,有可能回收掉正在后台运行的服务。

解决方案:使用前台服务,它不会由于系统内存不足而被回收。

与后台服务区别:它会一直有一个正在运行的图标在系统的状态栏显示,下拉状态后可看到更加详细的信息,非常类似于通知的效果。当然有些项目会由于特殊需求必须使用前台服务。比如墨迹天气:它的服务在后台更新数据的同时,还会在系统状态栏一直显示当前的天气信息。

用法:通过startForeground()就会让后台服务变成一个前台服务,并在系统状态栏显示出来。第一个参数是id,第二个参数怎是构建出的Notification对象。

public class MyService extends Service {……@Overridepublic void onCreate() {super.onCreate();Notification notification = new Notification(R.drawable.ic_launcher, "Notification comes", System. currentTimeMillis());Intent notificationIntent = new Intent(this, MainActivity.class);PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);notification.setLatestEventInfo(this, "This is title", "This iscontent", pendingIntent);startForeground(1, notification);Log.d("MyService", "onCreate executed");}……}
2、使用IntentService

需求:服务中的代码默认运行在主线程当中,如果直接在服务里处理一些耗时操作,容易出现ANR。

解决方案1:在服务的具体方法里开启一个子线程,去处理耗时操作。

@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {new Thread(new Runnable() {@Overridepublic void run() {// 处理具体的逻辑}).start();return super.onStartCommand(intent, flags, startId);}
如果想让服务在线程执行完后自动停止,只需在上面的run()处理完具体逻辑后调用stopSelf()。

解决方案2:为了可以简单创建一个异步的、会自动停止的服务,Android专门提供了一个IntentService类。

此方案优点:相比方案1来说,它集成开启线程和自动停止。

public class MyIntentService extends IntentService {public MyIntentService() {super("MyIntentService"); // 必须调用父类的有参构造函数}@Overrideprotected void onHandleIntent(Intent intent) {// 打印当前线程的idLog.d("MyIntentService", "Thread id is " + Thread.currentThread().getId());}@Overridepublic void onDestroy() {super.onDestroy();Log.d("MyIntentService", "onDestroy executed");}}
onHandleIntent():此方法在子线程中,可执行具体的逻辑。上面重写onDestroy()只是为了验证服务是否停止。





0 0
原创粉丝点击