Service是Android系统中的四大组件之一,它是一种长生命周期的,没有可视化界面,运行于后台的一种服务程序。
Service就是一种运行在后台的组件,甚至从始至终用户都不需要和它进行交互,比如Service可以处理一些网络事物,播放音乐,I/O文件传输,或者和Content provider交互。如果需要注意的是,一个Service运行在它宿主线程的主线程上,Service不会自己创建一个新的线程,也不会在一个独立的线程上运行(除非你指定它),也就是说如果你要用Service来执行大量的占用CPU的操作,或者是运行耗时的阻塞操作,例如后台播放MP3,或者网络事物,那么你就应该创建一个新的线程来实现Service去完成这些任务,通过创建新的线程,你降低ANR(Application Not Respond)的风险,不影响主线程保持与用户的交互。
线程和Service就有一定的相似性,到底什么时候用Service,什么时候用Thread呢?
在Google官方文档里这样写:如果你需要在主线程之外来完成你的任务,但只发生在在用户与当前Application进行交互的时候,就创建线程来实现它,而不是Service。比如说,如果你想播放音乐,但是只想在当前Activity运行的时候,如果当前Activity死掉了,那么也就停止播放,你可以在onCreate()中创建新的线程,在onStart()中开始运行线程,然后在onStop()中停止这个线程。你也可以考虑用异步加载AsyncTask或者HandlerThread的方式来代替传统的线程。谨记一个Service是在当application的主线程上跑,如果要进行大量的操作,那么就创建一个新的线程来实现Service。
一般在不需要交互的情况下用startService()来启动服务。
public class MusicService extends Service
重写onCreate方法
Service在创建时调用的方法,可以用来做数据初始化,Service在没有停止之前,只会执行一次。
实现onBind方法
由于Service是一个抽象类,定义了一个onBind抽象方法,所以必须实现此抽象方法,return null 即可,此方法在startService方式用不上,无需理会。
重写onStartCommand方法
Service创建后会调用onStartCommand,此方法中可以接收调用者传递过来的参数,并且可以编写需要的逻辑代码,当重复调用Service时,onStartCommand会重复执行,onStart方法已弃用。
重写onDestroy方法
Service在退出时调用,此方法中可以编写释放资源的操作。
在AndroidManifest文件中注册Service
<service android:name="com.lenovo.mymediaplayer.service.MusicService" >
service>
在onStartCommand()中接受Intent ;
Intent intent = new Intent(this, HelloService.class);
startService(intent);
public class MyBindService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
public class MyBinder extends Binder{
public MyBindService getService(){
return MyBindService.this;
}
}
private MyBinder myBinder = new MyBinder();
public IBinder onBind(Intent intent) {
return myBinder;
}
public void run(){
new Thread(new Runnable() {
@Override
public void run() {
int count = 0;
while (count < 10) {
Log.e(TAG, "run: -------" + count);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
}
}
}).start();
}
private ServiceConnection connection = new ServiceConnection() {
/**
* Service连接成功时调用
* @param name
* @param service
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(TAG, "onServiceConnected: -------------------");
//获取Service返回的MyBindService对象
MyBindService myBindService = ((MyBindService.MyBinder)service).getService();
//调用MyBindService的run方法
myBindService.run();
}
/**
* Service因为一些原因被破坏或销毁的时候调用
* @param name
*/
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG, "onServiceDisconnected: ---------------------------" );
}
};
Intent intent = new Intent(this,MyBindService.class);
bindService(intent,connection,BIND_AUTO_CREATE);
unbindService(connection);
public class MyIntentService extends IntentService {
private String TAG = "MyIntentService";
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
int count = 0;
while (count<10){
Log.e(TAG, "onHandleIntent: ------------"+count );
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
}
}
}
Intent intent = new Intent(this,MyIntentService.class);
startService(intent);
可以看到,我们执行了一个while循环耗时操作,但是并没有写在子线程中,这是因为它会自己创建子线程进行处理,并且它是串行的,也就是当前这个线程执行完毕才会执行下一个线程