BindService生命周期
startService 启动服务后,会执行如下生命周期:onCreate() ->onStartCommand() - -> onDestroy() 。具体看一下它的几个生命周期方法:
⚫ onCreate() :首次启动服务的时候,系统会调用这个方法,在onStartCommand 和
onBind 方法之前,如果服务已经启动起来了,再次启动时,则不会调用此方法,
因此可以在onCreate 方法中做一些初始化的操作,比如要执行耗时的操作,可以
在这里创建线程,要播放音乐,可以在这里初始化音乐播放器
⚫ onStartCommand(): 当通过startService 方法来启动服务的时候,在onCreate 方法
之后就会回调这个方法,此方法调用后,服务就启动起来了,将会在后台无限期
的运行,直到通过stopService 或者 stopSelf 方法来停止服务。
⚫ onDestroy():当服务不再使用且将被销毁时,系统将调用此方法。服务应该实现此
方法来清理所有资源,如线程、注册的侦听器、接收器等。 这是服务接收的最
后一个调用。
前面讲的通过startService 方式启动的服务是与组件相独立的,即使启动服务的组件
被销毁了,服务仍然在后台运行不受干扰。但是通过bindSerivce 方式绑定的服务就不
一样了,它与绑定组件的生命周期是有关的。如下:
⚫ 多个组件可以绑定到同一个服务上,如果只有一个组件绑定服务,当绑定的组件
被销毁时,服务也就会停止了。
⚫ 如果是多个组件绑定到一个服务上,当绑定到该服务的所有组件都被销毁时,服
务才会停止。
⚫ bindService 绑定服务和startService 的生命周期是不一样,bindServie 的生命周期如
下:onCreate -> onBind -> onUnbind ->onDestroy,其中重要的就是onBind 和
onUnbind 方法。
⚫ onBind() :当其他组件想通过bindService 与服务绑定时,系统将会回调这个方
法,在实现中,你必须返回一个IBinder接口,供客户端与服务进行通信,必
须实现此方法,这个方法是Service 的一个抽象方法,但是如果你不允许绑定
的话,返回null 就可以了。
⚫ onUnbind() :当所有与服务绑定的组件都解除绑定时,就会调用此方法
验证多组件绑定
多个组件绑定同一服务
⚫ Service 是支持多个组件绑定在同一个服务上的,第一个
组件绑定是会回调 onCreate 生命周期方法,后续的绑定
只会调用onBind方法,返回IBinder给客户端。
⚫ 当绑定在服务上的组件都调用unbindService 解除绑定服
务或者组件本身就已经被系统回收,那么服务也就会被
停止回收了,会回调onUnbind 和 onDestroy 方法。
源代码
(1) activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout 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"
android:orientation="horizontal"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="bindClick"
android:text="绑定服务1"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="callClick"
android:text="调用服务中的方法"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="unbindClick"
android:text="解绑服务"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="tochild"
android:text="to child"/>
</TableLayout>
(2)再建一个activity_main2.xml(表示第二个组件)
<?xml version="1.0" encoding="utf-8"?>
<TableLayout 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"
android:orientation="horizontal"
tools:context=".MainActivity2">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="bindClick"
android:text="绑定服务2"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="callClick"
android:text="调用服务中的方法"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="unbindClick"
android:text="解绑服务"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="toparent"
android:text="to parent"/>
</TableLayout>
(3)MainActivity.java
package com.example.bindservice;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
public class MainActivity extends AppCompatActivity {
MyConn myConn;
MyService.MyBinder myBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//跳转到子页面
public void tochild(View v){
Log.v("chendandan","to child page");
Intent intent=new Intent(MainActivity.this,MainActivity2.class);
startActivity(intent);
}
//绑定服务
public void bindClick(View view){
Log.v("chendandan","bindClick()");
if(myConn==null){
myConn=new MyConn();
}
Intent intent=new Intent(MainActivity.this,MyService.class);
intent.setType("main");
bindService(intent,myConn,BIND_AUTO_CREATE);
}
//调用服务中的方法
public void callClick(View view){
Log.v("chendandan","callClick()");
myBinder.methodInBinder();
}
//解除绑定
public void unbindClick(View view){
Log.v("chendandan","unbindClick()");
if(myConn!=null){
unbindService(myConn);
myConn=null;
}
}
public class MyConn implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder iBinder) {
myBinder = (MyService.MyBinder) iBinder;
Log.v("chendandan","服务成功绑定,内存地址为:"+myBinder.toString());
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.v("chendandan","服务成功解绑");
}
}
}
(4)MainActivity2.java
package com.example.bindservice;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
public class MainActivity2 extends AppCompatActivity {
MyConn myConn;
MyService.MyBinder myBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
}
public void toparent(View v){
Log.v("chendandan","to parent page");
Intent intent=new Intent(MainActivity2.this,MainActivity.class);
startActivity(intent);
}
public void bindClick(View view){
Log.v("chendandan","bindClick()");
if(myConn==null){
myConn=new MyConn();
}
Intent intent=new Intent(MainActivity2.this,MyService.class);
intent.setType("child");
bindService(intent,myConn,BIND_AUTO_CREATE);
}
public void callClick(View view){
Log.v("chendandan","callClick()");
myBinder.methodInBinder();
}
public void unbindClick(View view){
Log.v("chendandan","unbindClick()");
if(myConn!=null){
unbindService(myConn);
myConn=null;
}
}
public class MyConn implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder iBinder) {
myBinder = (MyService.MyBinder) iBinder;
Log.v("chendandan","服务成功绑定,内存地址为:"+myBinder.toString());
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.v("chendandan","服务成功解绑");
}
}
@Override
public void onDestroy(){
Log.v("chendandan","子页面被销毁");
super.onDestroy();
}
}
(5)新建一个MyService.java
package com.example.bindservice;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
class MyBinder extends Binder{
public void methodInBinder(){
Log.v("chendandan","执行MyBinder中的methodBinder()方法");
method();
}
}
public void method(){
Log.v("chendandan","执行MyService中的method()方法");
}
@Override
public void onCreate(){
Log.v("chendandan","创建服务,执行onCreate()方法");
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
Log.v("chendandan","绑定服务,执行onBind()方法");
return new MyBinder();
}
@Override
public boolean onUnbind(Intent intent){
Log.v("chendandan","解绑服务,执行onUnbind()方法");
return super.onUnbind(intent);
}
@Override
public int onStartCommand(Intent intent,int flags,int startId){
Log.v("chendandan","call onStartCommand()");
return super.onStartCommand(intent,flags,startId);
}
@Override
public void onDestroy(){
Log.v("chendandan","call Destroy...");
}
}
(6)在AndroidManifest.xml中设置主页面调用子页面的方式,以及注册子组件:
<activity android:name=".MainActivity" android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity2">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
运行结果:
如果文章对你有帮助,不要忘了给我点个赞吼( ̄▽ ̄)~
欢迎关注我的微信公众号:松鼠技术站