Service
Service的作用
Service一般用于在后台处理耗时任务,比如下载任务。
Service的生命周期
生命周期方法 | 作用 |
---|---|
IBinder onBind(Intent intent) | 绑定服务的时候调用 |
int onStartCommand(Intent intent, int flags, int startId) | 服务启动的时候调用 |
boolean onUnbind(Intent intent) | 服务被解绑的时候调用 |
void onCreate() | 服务被创建的时候调用 |
startService(Intent service) | 启动服务 |
stopService(Intent name) | 停止服务 |
bindService(Intent service, ServiceConnection conn, |
int flags) | 绑定服务 |
| unbindService(ServiceConnection conn) | 解绑服务,只会执行一次,多次解绑服务会出现错误 |
启动服务和停止服务
启动服务需要调用startService()方法,停止服务需要调用stopService();服务启动后,其生命周期独立于启动它的Activity,即使Activity销毁了,服务也会在后台继续运行,除非我们停止服务或者服务已执行完成。
接下来通过一个例子来说明:
布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<Button
android:id="@+id/btn_start"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="启动服务"/>
<Button
android:id="@+id/btn_stop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="停止服务"/>
<Button
android:id="@+id/btn_bind"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="绑定服务"/>
<Button
android:id="@+id/btn_unbind"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="解绑服务"/>
</LinearLayout>
MyService类
public class MyService extends Service {
private static final String TAG = "MyService";
private int sum = 0;
public MyService() {
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind: 绑定服务");
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: 启动服务");
return super.onStartCommand(intent, flags, startId);
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind: 解绑服务");
return super.onUnbind(intent);
}
@Override
public void onCreate() {
Log.d(TAG, "onCreate: 创建服务");
super.onCreate();
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy: 服务销毁了");
super.onDestroy();
}
}
Activity中的代码
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private static final String TAG = "MainActivity";
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private Button btnStart;
private Button btnStop;
private Button btnBind;
private Button btnUnbind;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnStart = findViewById(R.id.btn_start);
btnStop = findViewById(R.id.btn_stop);
btnBind = findViewById(R.id.btn_bind);
btnUnbind = findViewById(R.id.btn_unbind);
btnStart.setOnClickListener(this);
btnStop.setOnClickListener(this);
btnBind.setOnClickListener(this);
btnUnbind.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_start:
Intent intent1 = new Intent(this,MyService.class);
startService(intent1);
break;
case R.id.btn_stop:
Intent intent2 = new Intent(this,MyService.class);
stopService(intent2);
break;
case R.id.btn_bind:
Intent intent3 = new Intent(this,MyService.class);
//第三个参数:服务绑定的方式,只要绑定存在就自动创建service
bindService(intent3, serviceConnection,BIND_AUTO_CREATE);
break;
case R.id.btn_unbind:
Intent intent4 = new Intent(this,MyService.class);
unbindService(serviceConnection);
break;
}
}
}
接下来我们来看一下实际的运行效果:
当我们依次点击启动服务、停止服务时,会打印出如下的日志;
那么,如果我们再点击启动服务以后,再次点击启动服务会是什么样的效果呢?可以看到当再次点击启动服务的时候,只会在日志中打印启动服务的语句,并不会重新创建服务,也就是说,如果服务已经创建了,后续重复启动,操作的都是同一个服务;
绑定服务和解绑服务
服务的绑定需要通过ServiceConnection对象来实现,绑定和解绑的时候需要传入同一个ServiceConnection对象。
绑定服务需要使用 bindService()方法,这个方法的第一个参数是Intent类型的对象,第二参数是ServiceConnection类型的对象,第三个参数一般为BIND_AUTO_CREATE,表示服务没有被创建的时候会自动创建服务。
解绑服务使用unBindService()方法,这个方法的参数就是绑定服务时传入的ServiceConnection对象;
当我们依次点击绑定服务、解绑服务按钮时(在点击绑定之前服务没有被创建),可以看到如下效果,这说明了:如果服务不存在,点击绑定服务按钮会创建服务并绑定服务,点击解绑服务按钮会解绑服务并销毁服务;
如果在点击绑定服务、解绑服务按钮时,如果服务已经被创建的效果会是什么样的呢?
如果是点击绑定服务后,服务被创建了,那么再次点击绑定服务不会有任何输出:
如果是点击启动服务、绑定服务的话,会出现如下的效果,可以看到绑定服务只调用了onBind()方法:
这个时候我们再点击解绑服务,可以看到只解绑了服务并没有销毁服务:
只有再点击停止服务,才会销毁服务:
总结:
如果服务不存在:onCreate–>onBind–>onUnbind–>onDestory;
如果服务已存在:那么bindService方法只能使onBind方法被调用,而unbindService方法只能使onUnBind方法被调用;
绑定服务的应用
绑定服务的最大作用是实现对Service执行的任务进行进度监控。
IBinder是用于远程操作对象的一个基本接口。
MyService类
这个类在onCreate方法中开启线程执行耗时任务;onBind方法需要返回一个IBinder对象,我们这里是创建一个类继承了Binder类,Binder实现了IBinder接口的所有方法;MyBinder定义了一个返回sum的方法。onBind方法返回的对象会作为onServiceConnected方法的参数,所以我们可以在onServiceConnected方法中调用getProgress方法得到sum。
public class MyService extends Service {
private static final String TAG = "MyService";
private int sum = 0;
public MyService() {
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind: 绑定服务");
//这里返回的对象会作为onServiceConnected方法的参数
return new MyBinder();
}
class MyBinder extends Binder {
//获取返回结果
public int getProgress() {
return sum;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: 启动服务");
return super.onStartCommand(intent, flags, startId);
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind: 解绑服务");
return super.onUnbind(intent);
}
@Override
public void onCreate() {
Log.d(TAG, "onCreate: 创建服务");
//执行耗时操作
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
sum += i;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
super.onCreate();
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy: 服务销毁了");
super.onDestroy();
}
}
MainActivity类
ServiceConnection接口的onServiceConnected方法当客户端和service正常连接的时候,执行绑定服务会被调用,而onServiceDisconnected方法会在客户端和service失去连接的时候调用。
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private static final String TAG = "MainActivity";
private ServiceConnection serviceConnection = new ServiceConnection() {
//当客户端和service正常连接的时候,执行绑定服务会被调用
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "onServiceConnected: 正常连接");
MyService.MyBinder binder = (MyService.MyBinder)service;
int progress = binder.getProgress();
Log.d(TAG, "onServiceConnected: 进度: " + progress);
}
//当客户端和service失去连接的时候调用
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "onServiceDisconnected: 失去连接");
}
};
private Button btnStart;
private Button btnStop;
private Button btnBind;
private Button btnUnbind;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnStart = findViewById(R.id.btn_start);
btnStop = findViewById(R.id.btn_stop);
btnBind = findViewById(R.id.btn_bind);
btnUnbind = findViewById(R.id.btn_unbind);
btnStart.setOnClickListener(this);
btnStop.setOnClickListener(this);
btnBind.setOnClickListener(this);
btnUnbind.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_start:
Intent intent1 = new Intent(this,MyService.class);
startService(intent1);
break;
case R.id.btn_stop:
Intent intent2 = new Intent(this,MyService.class);
stopService(intent2);
break;
case R.id.btn_bind:
Intent intent3 = new Intent(this,MyService.class);
//第三个参数:服务绑定的方式,只要绑定存在就自动创建service
bindService(intent3, serviceConnection,BIND_AUTO_CREATE);
break;
case R.id.btn_unbind:
Intent intent4 = new Intent(this,MyService.class);
unbindService(serviceConnection);
break;
}
}
}
当我们点击启动服务按钮,然后点击绑定服务按钮,然后点击解绑服务按钮,就可以看到如下的日志了,可以看到打印出了我们想要的结果。