Android四大组件(Service篇)

来源:互联网 发布:怎样删除精选淘宝 编辑:程序博客网 时间:2024/06/16 14:51

什么是Service

Service是运行于Android后台的程序操作,无用户交互界面。

创建一个服务,只需要继承android.app.Service类即可。而其中必须实现的方法只有一个

@Overridepublic IBinder onBind(Intent intent) {    // TODO: Return the communication channel to the service.}

若不实现该方法,将会抛出异常。该方法将返回一个IBinder对象。IBinder是一个Interface,因此,我们需要在Service中定义一个Binder类(该类实现了IBinder接口),并在onBinder中返回。而绑定Service的Activity可通过强行转换,获取自定义的Binder类。

当然,如果不想Service被绑定,可以不定义,返回null即可。

注:作为Android的四大组件,Service也需要在Manifest中进行声明。如果使用Android Studio的创建向导,声明将被自动添加。

<application        android:allowBackup="true"        android:label="@string/app_name"        android:supportsRtl="true">        <service            android:name=".myService"            android:enabled="true"            android:exported="true"></service>    </application>

注:enabled表示是否启用这个Service,exported表示该服务能否被其他程序访问。

Service中常用的监听方法

(1)public void onCreate()
Service是一个单例。当Service第一次被创建时,该方法被调用。

(2)public int onStartCommand(Intent intent, int flags, int startId)
当Service被启动时,该方法被调用。每个Service都可以被启动多次,因此,该方法可以被调用多次。

(3)public void onDestroy()
当Service被销毁时,该方法被调用。

(4)public IBinder onBind(Intent intent)
当Service被绑定时,该方法被调用。

(5)public boolean onUnbind(Intent intent)
当Service被解绑时,该方法被调用。

如何触发Service

(1)Start/Stop方式

启动Service

intent=new Intent(this, myService.class);startService(intent);

若此时Service未创建,则将依次触发

myServiceonCreateonStartCommand

否则,仅触发

onStartCommand

停止服务

intent=new Intent(this, myService.class);stopService(intent);

停止服务将会触发

onDestroy

onDestroy跟onCreate一样,仅被触发一次。

(2)Bind/Unbind方式

若Service提供多种服务,比如func1,func2,我们该如何调用呢?
此时startService/stopService方式便不能满足要求了。因此,我们通过绑定的方式,获取服务代理,该代理即为Binder。

(a)在自定义的Binder类当中实现func1,func2。

public class myBinder extends Binder {    private final String TAG=getClass().getName();    public void fun1(){        Log.i(TAG, "fun1: ");    }    public void fun2(){        Log.i(TAG, "fun2: ");    }}

(b)当Activity绑定Service时,将自定义的Binder实例提通过onBind接口供给Activity。

public class myService extends Service {    private final String TAG=getClass().getName();    private myBinder m_Binder;    public myService() {        Log.i(TAG, "myService: Thread id = "+Thread.currentThread().getId());        m_Binder=new CalculateBinder();    }    @Override    public void onDestroy() {        m_Binder=null;        super.onDestroy();    }    @Override    public IBinder onBind(Intent intent) {        // TODO: Return the communication channel to the service.        return m_Binder;    }}

(c)ServiceConnection接口
绑定Service是异步操作,因此,需要回掉方法来通知Activity,是否已经与Service建立连接。

ServiceConnection m_servic eConnection=new ServiceConnection() {    @Override    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {        m_Binder=(CalculateBinder) iBinder;    }    @Override    public void onServiceDisconnected(ComponentName componentName) {        m_Binder=null;    }};

若连接建立成功,onServiceConnected方法将会被触发,iBinder即为onBind方法返回的Service代理。

这里需要对onServiceDisconnected进行特殊说明。onServiceDisconnected方法仅在Service异常丢失(并非onDestroy)时触发。系统资源不足时,会对资源进行回收,而Service的优先级别并不高,因此可能触发Service的丢失情况。

(d)绑定Service

intent=new Intent(this, myService.class);bindService(intent,m_serviceConnection, Context.BIND_AUTO_CREATE);

bindService将触发以下Service生命周期监听方法

onCreateonBind

(e)解绑Service

unbindService(m_serviceConnection);

若在bindService前,Service未被启动,或未被多个Activity绑定,则unbindService将触发以下Service生命周期监听方法

onUnbindonDestroy

若bindService前,Service已被启动,或被多个Activity绑定,则unbindService将仅触发onUnbind方法。

需要注意的是,即使startService()仅被调用了一次,stopService()也可被多次调用。但对于bindService和unbindService就不同了。bindService可被多次调用。unbindService仅能被调用一次。若多次调用,将引发异常。

java.lang.IllegalArgumentException: Service not registered: com.breakloop.servicedemo.MainActivity$1@2ebc9d4

Service的问题

问题来了~
(1)Service能否关闭自己?

当然可以!在需要的位置,调用stopSelf()即可。

(2)Service是否在主线程中?

主线程!可以在Activity和Service中分别打印当前线程ID,会发现两者相同。

Thread.currentThread().getId();

IntentService

由Activity来停止Service的运行,并不可取。因为当前Activity并不知道,Service是否还被其他调用者使用。同时,由于处于主线程,如果Service来处理耗时任务,则会造成ANR(Application No Response)。为了解决这两个问题,Android提供了IntentService。
(当然,也在Service中使用线程和连接计数器来规避这两个问题。)

IntentService使用非常方便。当任务完成后,会自动停止,且任务在子线程中执行。因此,跟AsynTask类似。

创建一个自定义的IntentService,仅需要继承android.app.IntentService,并实现抽象方法protected void onHandleIntent(Intent intent),该方法将在线程中完成所有任务。类似于AsynTask的doBackground。

public class myIntentService extends IntentService {    private final String TAG=getClass().getName();    public myIntentService() {        super("myIntentService");    }    @Override    protected void onHandleIntent(Intent intent) {        //TODO        Log.i(TAG, "onHandleIntent");    }    @Override    public void onCreate() {        Log.i(TAG, "onCreate");        super.onCreate();    }    @Override    public void onDestroy() {        Log.i(TAG, "onDestroy");        super.onDestroy();    }}

IntentService需要使用startService类启动。

intent=new Intent(this,myIntentService.class);startService(intent);

而启动后,将依次触发IntentService的以下生命周期监听方法。

onCreateonHandleIntentonDestroy

以上,都是在同一进程中的service访问方法。
当然,Service也可以跨进程访问,通常使用AIDL的方式。将在单独的篇幅中进行介绍。

原创粉丝点击