后台服务(Service)简述

来源:互联网 发布:短租房网站源码php 编辑:程序博客网 时间:2024/05/02 02:43

一、简介

Service是应用的后台服务,它用来执行不需与用户交互的、耗时的操作,或者给其他应用提供一些功能。Service默认运行在用户界面(Activity)所在的主线程中,所以它的执行速度越快越好。如果有耗时较长或者会阻塞的操作,可以在Service中创建一个线程去完成它。若Service的执行时间超过5秒,系统会抛出“应用程序无响应(ANR)”的对话框。

二、注册Service

所有Service都应该在所在应用的AndroidManifest.xml中注册相应的标签,否则将无法被Activity连接(包括start和bind)。

<manifest ... >    ...    <application ... >        <service             <!-- 设置本服务的类名 -->            android:name=".TestService"             <!-- 设置本服务作为一个单独的进程。省略这行代码的话,它将运行于主线程中 -->            android:process=":任意名称"            <!-- 是否接收其他应用的启动请求 -->            android:exported="false"      />        ...    </application>  </manifest>

三、连接Service

Service可以同时被多个Activity经调用startService()或bindService()来连接,每次它都会以onStartCommand()或onBind()来响应,但其onCreate()只会在Service对象首次创建时调用。如果不想提供绑定,可以让onBind()返回null。

四、断开Service

绑定上的Activity可以调用unbindService()来解除绑定。当所有Activity都解绑后,系统就会调用服务的onUnbind()方法(若无其他Activity启动服务,则服务会被销毁)。启动服务的Activity可以调用stopService()来停止服务,服务也可以自己调用stopSelf()来停止,但这两种方法的前提是服务未被绑定。停止时,系统会调用onDestory()来销毁服务。

service_binding_tree_lifecycle.png

五、生命周期

Service的生命周期从onCreate()开始,到onDestroy()或者被系统杀死时结束。在空闲内存不足时,系统会杀掉一些进程,Service已启动的时间越长,越容易被系统杀死。在Service被可见进程所绑定期间,它所在的进程也将被认为是可见进程(除非绑定时另行指定),使得它的进程不那么容易被杀死。当Service正在运行onCreate()、onStartCommand()、onDestory()时,或者调用了startForeground(),系统会把它所在的进程当做前台进程,这样只有在极端低内存的情况下它的进程才会被杀死。

六、线程安全

Android提供了一个线程安全的、继承自Service的IntentService类,继承它之后只需实现其onHandleIntent方法则可,该方法负责具体的工作任务。IntentService仅支持startService(),而不支持bindService()。每当有Activity连接上来时,它都会创建一个工作线程加入到由它管理的工作队列中。工作线程们依次调用onHandleIntent(),执行完毕后才轮到下一个。当所有的工作线程都干完活时,IntentService对象会自动销毁,以节省资源。

public class TestIntentService extends IntentService {    public IntentService()     {        super("随便起个名字");    }    protected void onHandleIntent(Intent intent)    {        /**         * 工作线程们依次进来干活,执行完毕后才轮到下一个。         * 任务相关信息会经由startService(intent)的参数传进来。         */    }}

七、样例代码

package com.example.wesnoth;import android.app.Activity;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.os.IBinder;public class TestActivity extends Activity{    private Intent intent = new Intent(TestActivity.this, TestService.class);    private TestService.MyBinder myBinder = null;    private TestServiceConnection testServiceConnection = new TestServiceConnection();    @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.XXXXXXX);        // 注意:应当使用指定了目标Service类名的        // 显式Intent来启动Service。        // 否则Android 5.0(API 21)以上系统会抛出异常        Intent intent = new Intent(this, DownloadService.class);        if (true)        {            /**             * 启动服务。             */            startService(intent);        }        else        {            /**             * 绑定服务。             */            bindService(intent, testServiceConnection, BIND_AUTO_CREATE);        }    }    @Override    protected void onDestroy()    {        super.onDestroy();        if(true)        {                               /**             * 停止服务。             * 此时不管是否有其他Activity连接,都会进入到Service.onDestroy()             */            stopService(intent);        }        else        {            /**             * 解绑服务             */            unbindService(intent);        }    }    class TestServiceConnection implements ServiceConnection    {        @Override        public void onServiceConnected(ComponentName name, IBinder service)        {            /**             * 当绑定Service成功时,进入此方法             */            myBinder = (TestService.MyBinder)service;        }        @Override        public void onServiceDisconnected(ComponentName name)        {            /**             * 当Service所在的进程崩溃掉或者被杀掉时,进入此方法。             * 此时并不会断开与Service的连接,等到Service所在的进程重启时,             * 会重新调用onServiceConnected()             */            myBinder = null;        }    }}
package com.example.wesnoth;import android.app.Service;import android.content.Intent;import android.os.Binder;import android.os.IBinder;public class TestService extends Service{    private MyBinder myBinder = new MyBinder();    @Override    public void onCreate()    {        /**         * 本方法只会在Service对象首次创建时调用。         */        super.onCreate();    }    @Override    public int onStartCommand(Intent intent, int flags, int startId)    {        // 可以在这里创建处理任务的线程。        // 线程完成任务后可以调用stopSelf(startId);        // 如果最后一个启动服务的ID与startId匹配,        // 就会销毁服务,否则不销毁。        /**         * 当有Context对象调用startService()时,调用此方法。         */        return super.onStartCommand(intent, flags, startId);    }    @Override    public IBinder onBind(Intent intent)    {        /**         * 当首次被Activity绑定时,调用此方法。         * 系统会保存IBinder,         * 后续的绑定将不调用此方法而是直接返回它。         * 如果不想提供绑定,可以返回null         */        return myBinder;    }    @Override    public boolean onUnbind(Intent intent)    {        /**         * 当所有已绑定的Activity都调用了unbindService()来解绑,         * 就会调用onUnbind()。         */        return super.onUnbind(intent);    }    @Override    public void onDestroy()    {        /**         * 当所有已绑定的Activity都调用了unbindService()来解绑,         * 此时若没有任何Activity已通过startService来连接的话,才会调用onDestory()。         * 若某个Activity调用了stopService,或者Service自己调用了stopSelf(),         * 此时不管还有没有其他连接,都会调用onDestroy()。         */        super.onDestroy();    }    // 注意:这个Binder的所有公开方法都需要做到线程安全    public class MyBinder extends Binder    {        // 这个方法可以给bind上的Activity调用        public void doSomething()        {            // 处理任务        }    }}
0 0
原创粉丝点击