Service详解_BoundService

本文介绍如何使用LocalBind实现Android应用内部组件与Service之间的交互。通过创建Binder实例并将其返回给客户端,客户端能够调用Service提供的公共方法。文章还提供了具体的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为了便于对本文的理解,请先阅读上一篇文章《Service详解_StartedService》。从上篇文章可以知道,在同一个APP内,其它组件能启动和停止一个StartedService,但是不能调用Service内的函数,不能获取Service的返回值。如果要实现组件与Service交互,就要使用BoundService。BoundService是Client-Server工作模式中的Server,其它组件通过bindService()绑定到它,建立一个长连接,并用IBinder与Service进行交互。BoundService分为:
1、 Local Bind:组件与Service运行在同一进程中,Service只在应用内使用,不会被跨进程访问。通过Binder创建接口,实现组件与Local Service交互。
2、 Remote Bind:组件与Service运行在不同进程中,有来自其他进程的Client访问Service。使用AIDL定义进程间通信接口,实现组件与Remote Service进程间通信。
本文主要讲解Local Bind,关于Remote Bind请阅读下一篇文章《Service详解_AIDL》

创建接口

通过扩展Binder类创建接口,用onBind()返回Binder实例,下面是具体步骤:
1、 在Service中创建一个Binder实例,执行以下操作之一:
•包含Client可以调用的public函数。
•返回Service的实例,用于Client调用Service的public函数。
•返回Service中的其它类的对象,用于Client调用Service的public函数。
2、 通过onBind()回调函数返回这个Binder实例。

如下代码展示一个Service用Binder向Client提供交互接口:

public class LocalService extends Service {

    //用于返回给Clients的Binder
    private final IBinder mBinder = new LocalBinder();

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    //通过扩展Binder创建接口
    public class LocalBinder extends Binder {
        public LocalService getService() {
            //返回LocalServiceA的实例,Clients用于调用LocalServiceA中的public方法
            return LocalService.this;
        }
    }

    //Client通过Binder可以调用Service中的这个函数
    public int plus(int a, int b) {
        return a + b;
    }
}

LocalBinder用用getService()向Client提供获取Service实例的方法,Client就能调用Service中的函数(如plus(int a, int b))。

下面代码展示一个Activity绑定到Service,当点击按钮时调用plus(int a, int b)方法。

public class BindLocalServiceActivity extends Activity implements View.OnClickListener {

    private static final String TAG = "BindLServiceActivity";
    private Context mContext;
    private Button bindLocalServiceBtn;
    private Button unbindLocalServiceBtn;
    private Button plushBtn;
    private LocalService mLocalService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bind_local_service);
        mContext = this;
        bindLocalServiceBtn = (Button) findViewById(R.id.bind_local_service_btn);
        unbindLocalServiceBtn = (Button) findViewById(R.id.unbind_local_service_btn);
        plushBtn = (Button) findViewById(R.id.plus_btn);
        bindLocalServiceBtn.setOnClickListener(this);
        unbindLocalServiceBtn.setOnClickListener(this);
        plushBtn.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.bind_local_service_btn:
                Intent intent = new Intent(this, LocalService.class);
                bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
                break;
            case R.id.unbind_local_service_btn:
                unbindService(mConnection);
                Toast.makeText(mContext, "unbindService", Toast.LENGTH_SHORT).show();
                break;
            case R.id.plus_btn:
                if(mLocalService != null) {
                    int result = mLocalService.plus(1, 3);
                    Log.i(TAG, "plus result="+result);
                    Toast.makeText(mContext, "plus result="+result, Toast.LENGTH_SHORT).show();
                }else {
                    Log.e(TAG, "unbind error");
                    Toast.makeText(mContext, "unbind error", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
                Log.e(TAG, "onClick, unsupport type");
                break;
        }
    }

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Toast.makeText(mContext, "onServiceConnected", Toast.LENGTH_SHORT).show();
            LocalService.LocalBinder binder = (LocalService.LocalBinder)iBinder;
            mLocalService = binder.getService();
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Toast.makeText(mContext, "onServiceDisconnected", Toast.LENGTH_SHORT).show();
        }
    };
}

绑定Service

应用组件用bindService()绑定到Service,Service的onBind()返回一个IBinder,Client用这个IBinder与Service交互。绑定是异步进行的,bindService()会立刻返回,但在onServiceConnected()中接收到IBinder。Client绑定到Service的步骤如下:
1、 实现ServiceConnection并重写下面两个回调函数:
•onServiceConnected()
Client在这个回调函数中接收到onBind()返回的IBinder。
•onServiceDisconnected()
当与Service的连接意外中断时,如Service crash或被kill,会调用此回调函数。Client从Service解绑时,不调用此函数。

private ServiceConnection mConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        Toast.makeText(mContext, "onServiceConnected", Toast.LENGTH_SHORT).show();
        LocalService.LocalBinder binder = (LocalService.LocalBinder)iBinder;
        mLocalService = binder.getService();
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        Toast.makeText(mContext, "onServiceDisconnected", Toast.LENGTH_SHORT).show();
    }
};

2、 调用bindService()并传入ServiceConnection实例。

Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

3、 当系统调用onServiceConnected()后,Client就可以获取到IBinder。

@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
    Toast.makeText(mContext, "onServiceConnected", Toast.LENGTH_SHORT).show();
    LocalService.LocalBinder binder = (LocalService.LocalBinder)iBinder;
    mLocalService = binder.getService();
}

通过IBinder调用Service中的函数

int result = mLocalService.plus(1, 3);

4、 Client调用unbindService()与Service解绑。

unbindService(mConnection);

如果组件被销毁时仍然绑定了Service,那么组件销毁后就会和Service解绑。Client最好在与Service交互完后及时解绑,这样可以及时关闭空闲的Service。

BoundService的生命周期

如果一个BoundService没有调用过 onStartCommand(),那么所有Client与它解绑后,系统会销毁它;如果调用过onStartCommand(),那么必须用stopSelf()或stopService()停止Service。如果一个Service既能start又能bind, onUnbind()返回true,那么再次绑定会调用onRebind()。如下图所示:
这里写图片描述
图1:一个同时支持start和bind的service的生命周期

示例代码

本文档所有示例代码下载路径:http://download.youkuaiyun.com/download/jennyliliyang/10155100

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值