安卓开发基础篇——Anroid四大组件之Service

本文详细介绍了安卓开发中的Service组件,包括其启动方式、生命周期管理及与客户端的交互方式。特别是bindService和startService的区别,以及IntentService的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

安卓开发四大组件之一——Service,可以理解为幕后工作者,音乐词曲作家,哈哈。那么在开发中,音乐播放,下载文件,上载文件都用到service。
Service,分为本地服务和远程服务,区分是客户端和服务端是否在同一进程当中,在为本地服务,不在为远程服务,下面着重介绍本地服务,是安卓开发中最常用到的。
启动服务有两种方式,startService和bindService;
结束服务有两种方式,startService对应stopService或stopSelf,bindService对应unBindService;
startService和bindService;——两者之间的区别:startService启动服务后,客户端和服务端再就没有联系了,也就是之间没有通信,要结束服务,要不在启动服务的地方调用stopService或者在服务中调用stopSelf;bindService启动服务后,服务和客户端是有交互的,他们之间是通过binder对象进行交互的,要结束服务,在客户端调用unBindService,bindService在开发中是最常用的,所以着重要讲解。

切记在使用service时,一定要在AndroidManifest.xml中进行配置,如何配置,Activity怎么配置,服务就怎么配置。例如项目中下载视频服务的配置

  <!-- 下载视频服务器 -->
        <service android:name="com.suowei.appsuowei.service.UpVideoService"/>


1、startService:

生命周期:

onCreate ---> onStart ---> onDestory(Android 2.0以下版本中使用)

onCreate ---> onStartCommand ---> onDestory(Android2.0以上版本中使用)

当第一次调用startService后,先调用onCreate,再调用onStart或者onStartCommand,结束服务,调用onDestory,这里要特别注意的,如果已经启动了该服务,如果再次调用startService,那么不会调用onCreate,直接调用onStart或onStartCommand。

特别注意的是:onStartCommand方法返回一个int值,这个值有四种:

(1)START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
(2)START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统将会把它置为started状态,系统不会自动重启该服务,直到startService(Intent intent)方法再次被调用;。
(3)START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
(4)START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。

2、bindService:
生命周期:
bindService时:onCreate ---> onBind
unBindService时:onUnBind ---> onDestory
现在分步讲解:
在调用bindServcie时,要传入三个参数
this.bindService(intent, conn, Context.BIND_AUTO_CREATE);	
第一个参数intent为意图,用的滚瓜烂熟了吧
Intent intent=new Intent(this,UpVideoService.class);
第二个参数conn为实现了服务链接接口(ServiceConnection)的类的对象
private class UpVideoConnection implements ServiceConnection{
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
		}
		@Override
		public void onServiceDisconnected(ComponentName name) {}
	}
第一个方法在启动服务后链接上服务调用,第二个为断开服务链接时调用,大家注意,在第一个方法中传入了一个Ibinder接口变量,这个变量就是客户端与服务进行通信的桥梁纽带,客户端与服务端要通信,必须要拿到Service对象,才能调用Service中的公共方法,在android中的Service使用onBind的方法绑定服务时,返回一个实现IBinder接口的对象,所以在Service对象内部有一个Binder对象并返回,在这个对象中,写一个方法得到该Service,这样在上面的onServiceConnected中返回一个binder对象,用这个对象拿到Service对象,这样就可以随意调用Servcie中的公共方法了,实现了客户端有服务器端的通信
	
@Override
	public IBinder onBind(Intent intent) {
		return new VideoBinder;
	}


上面这个方法是用来返回Binder对象的


那么现在在服务里面写一个类(在这个类中写一个公共方法,getService,返回值为该服务)
public class VideoBinder extends Binder{
		public UpVideoService getService(){
			return UpVideoService.this;
		}
	}
那么现在就把这个类的对象进行返回,把null改为VideoBinder对象,
public IBinder onBind(Intent intent) {
		return new VideoBinder();}
那么这样,在客户端返回的Binder对象,调用自己的方法,就获取到了Service,接下来想怎么操作Service中的方法就看你的需要了。

3、IntentService
这家伙也得讲解下,不然学员又混淆了,首先IntentService是Service的子类,那么他就拥有Service所有的属性,既然是子类,那肯定有自己独特的好用之处了。在讲解这个IntentService之前,学员必须搞清一个问题,Service与Activity运行在不在同一个线程当中,答案是默认情况下他们都在进程的主线程中,哈哈,为了防止服务访问耗时操作或者线程阻塞,导致ANR,必须要新开线程,那么不得不在Service中编写耗时操作或者逻辑时,引入了IntentService,在intentService中,已经为你新开了一个线程,所以程序员在不必要新开线程了,而在IntentService中,只提供了一个方法
protected abstract void onHandleIntent(Intent intent);
这是一个抽象方法,要实现必须要重写了,通过查阅源代码,IntentService是通过Handler looper message的方式实现了一个多线程的操作,同时耗时操作也可以被这个线程管理和执行,同时不会产生ANR的情况。说来说去,大家记住喽,一代比一代永远强。
附上IntentService源码,有兴趣的可以看看,刚学习的不建议看,到此为止
private final class ServiceHandler extends Handler {  
    public ServiceHandler(Looper looper) {  
        super(looper);  
    }  
  
    @Override  
    public void handleMessage(Message msg) {  
        onHandleIntent((Intent)msg.obj);  
        stopSelf(msg.arg1);  
    }  
}  
  
/** 
 * Creates an IntentService.  Invoked by your subclass's constructor. 
 * 
 * @param name Used to name the worker thread, important only for debugging. 
 */  
public IntentService(String name) {  
    super();  
    mName = name;  
}  
  
/** 
 * Sets intent redelivery preferences.  Usually called from the constructor 
 * with your preferred semantics. 
 * 
 * <p>If enabled is true, 
 * {@link #onStartCommand(Intent, int, int)} will return 
 * {@link Service#START_REDELIVER_INTENT}, so if this process dies before 
 * {@link #onHandleIntent(Intent)} returns, the process will be restarted 
 * and the intent redelivered.  If multiple Intents have been sent, only 
 * the most recent one is guaranteed to be redelivered. 
 * 
 * <p>If enabled is false (the default), 
 * {@link #onStartCommand(Intent, int, int)} will return 
 * {@link Service#START_NOT_STICKY}, and if the process dies, the Intent 
 * dies along with it. 
 */  
public void setIntentRedelivery(boolean enabled) {  
    mRedelivery = enabled;  
}  
  
@Override  
public void onCreate() {  
    // TODO: It would be nice to have an option to hold a partial wakelock  
    // during processing, and to have a static startService(Context, Intent)  
    // method that would launch the service & hand off a wakelock.  
  
    super.onCreate();  
    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");  
    thread.start();  
  
    mServiceLooper = thread.getLooper();  
    mServiceHandler = new ServiceHandler(mServiceLooper);  
}  
  
@Override  
public void onStart(Intent intent, int startId) {  
    Message msg = mServiceHandler.obtainMessage();  
    msg.arg1 = startId;  
    msg.obj = intent;  
    mServiceHandler.sendMessage(msg);  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值