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>

运行结果:



如果文章对你有帮助,不要忘了给我点个赞吼( ̄▽ ̄)~
欢迎关注我的微信公众号:松鼠技术站