Android四大组件(Service篇)

什么是Service

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

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

@Override
public 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未创建,则将依次触发

myService
onCreate
onStartCommand

否则,仅触发

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生命周期监听方法

onCreate
onBind

(e)解绑Service

unbindService(m_serviceConnection);

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

onUnbind
onDestroy

若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的以下生命周期监听方法。

onCreate
onHandleIntent
onDestroy

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值