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);
具体代码如下:
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);
}
}
启动服务后依次会调用service中的onCreate->onStartCommand方法,其中onCreate只会调用一次,如果重新启动service的话,会重新调用onStartCommand方法。
onStartCommand方法的返回值
onStartCommand是有返回值的,返回值类型为int
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
通过看源码可以发现返回值有两个类型,分别是START_STICKY_COMPATIBILITY和START_STICKY
- START_STICKY_COMPATIBILITY:如果返回该值则不保证服务被杀死后会重新启动。
- START_STICKY:如果返回该值则服务在启动后被杀死会重新启动,会重新调用onStartCommand方法。
public @StartResult int onStartCommand(Intent intent, @StartArgFlags int flags, int startId) {
onStart(intent, startId);
return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
}
默认返回的是START_STICKY。
在service内部给activity创建启动服务的方法
在看Tinker的源码过程中发现,可以在service内部给activity创建启动服务的方法,代码如下,这样的好处就是提高了代码的封装性。
//对外提供启动servcie方法
public static void runService(Context context) {
try {
Intent intent = new Intent(context, MyService.class);
context.startService(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
bindService方法启动
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/
网友评论