Service 是什么?
Service 是一个一种能够长时间在后台运行并没有用户界面的应用组件.
Service 和 Thread 的区别
Service 翻译成中文就是 "服务",也许有人会认为服务就是能在后台执行耗时操作的,那就大错特错了,Service 是运行在主线程的,如果超过 20 秒还未处理完成则 Android 系统就会报 ANR 错误,即应用未响应.
下面我们来验证一下,首先在 Android Studio 中创建一个 MainActivity,再创建一个 Service,在 MainActivity 中启动 Service,并打印它们各自的所在的线程.
运行后的结果如下图.
public class MainActivity extends BaseActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void setContentView() {
setContentView(R.layout.activity_main);
//这里打印所在线程
Log.d(TAG, "Thread is" + Thread.currentThread().getName());
}
@Override
protected void initView() {
}
@Override
protected void initData() {
Intent intent = new Intent(MainActivity.this,MyService.class);
startService(intent);
}
}
public class MyService extends Service {
private static final String TAG = "MyService";
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
super.onCreate();
//这里打印所在线程
Log.d(TAG, "Thread is" + Thread.currentThread().getName());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
}
2018-01-14_140359.png
可以看出 Service 确实是运行在主线程中的,那么我们就不应该在 Service 中执行耗时的操作了,应该在子线程中执行耗时的操作.
Service 的启动方式
Service 一共有两种启动方式,一个是 startService,另一个是 bindService
startService 方法启动
这种方式启动 service 比较简单和启动一个 activity 差不多,步骤如下:
创建一个 service,并在 AndroidManifest 文件中进行注册(使用 Android Studio 自动生成的可忽略)
在 Activity 中创建
Intent intent = new Intent(MainActivity.this,MyService.class); startService(intent);
具体代码如下:
启动服务后依次会调用 service 中的 onCreate->onStartCommand 方法,其中 onCreate 只会调用一次,如果重新启动 service 的话,会重新调用 onStartCommand 方法.
public class MainActivity extends BaseActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void setContentView() {
setContentView(R.layout.activity_main);
Log.d(TAG, "Thread is " + Thread.currentThread().getName());
}
@Override
protected void initView() {
}
@Override
protected void initData() {
//启动服务
Intent intent = new Intent(MainActivity.this,MyService.class);
startService(intent);
}
}
onStartCommand 方法的返回值
onStartCommand 是有返回值的,返回值类型为 int
通过看源码可以发现返回值有两个类型,分别是 START_STICKY_COMPATIBILITY 和 START_STICKY
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
START_STICKY_COMPATIBILITY:如果返回该值则不保证服务被杀死后会重新启动.
START_STICKY:如果返回该值则服务在启动后被杀死会重新启动,会重新调用 onStartCommand 方法.
默认返回的是 START_STICKY.
public@StartResult int onStartCommand(Intent intent, @StartArgFlags int flags, int startId) {
onStart(intent, startId);
return mStartCompatibility ? START_STICKY_COMPATIBILITY: START_STICKY;
}
在 service 内部给 activity 创建启动服务的方法
在看 Tinker 的源码过程中发现,可以在 service 内部给 activity 创建启动服务的方法,代码如下,这样的好处就是提高了代码的封装性.
bindService 方法启动
//对外提供启动servcie方法
public static void runService(Context context) {
try {
Intent intent = new Intent(context, MyService.class);
context.startService(intent);
} catch(Exception e) {
e.printStackTrace();
}
}
bindService 启动的 service 会将 service 与 activity 绑定,activity 销毁了 service 也就停止了,步骤如下:
创建 BindService 服务端,继承自 Service 类,并在类中创建一个实现 IBinder 接口的实例对象并提供公共方法给客户端来调用.
从 onBind 方法回调方法返回此 Binder 实例
在客户端中,从 onServiceConnected 回调方法接收 Binder,并使用提供的方法调用绑定服务.
代码如下:
运行结果如下图.
public class MyService extends Service {
private static final String TAG = "MyService";
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// 返回IBinder对象
return new MyBinder();
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "Thread is " + Thread.currentThread().getName());
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
//给客户端提供服务的实例,从而可以来调用服务里的方法
public class MyBinder extends Binder {
public MyService getService(){
return MyService.this;
}
}
public void execute(){
Log.d(TAG, "activity 调用 service 里的方法成功");
}
}
public class MainActivity extends BaseActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void setContentView() {
setContentView(R.layout.activity_main);
Log.d(TAG, "Thread is " + Thread.currentThread().getName());
}
@Override
protected void initView() {
}
@Override
protected void initData() {
Intent intent = new Intent(MainActivity.this,MyService.class);
//绑定服务
bindService(intent,serviceConnection,BIND_AUTO_CREATE);
}
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//服务连接成功调用
Log.d(TAG, "service 连接成功");
MyService myService = ((MyService.MyBinder)service).getService();
myService.execute();
}
@Override
public void onServiceDisconnected(ComponentName name) {
//服务断开连接调用
}
};
}
2018-01-14_144844.png
bindService 执行的服务里方法的顺序如下:
onCreate->onBind->(Activity)onServiceConnected
通过绑定服务我们可以完成 activity 和 service 之间的通信,当然也可以使用广播.
欢迎大家来我的博客逛逛: http://yangchendev.top/
来源: http://www.jianshu.com/p/578fd91d6c9d