在活动中指挥服务

思路:首先要让活动和服务进行绑定,通过bindService()方法使得Activity和Service绑定在一起。注意bindService()方法要求传入Binder对象和ServiceConnection ,这就表示Binder和ServiceConnection 建立了联系。然后在Service中创建一个专门的Binder对象来提供相应的功能,之后在onBind() 方法中返回这个Binder对象到Activity中的ServiceConnection的onServiceConnected()方法中。这样在Activity中实现ServiceConnection时就可以在onServiceConnected()方法中使用Service中的Binder对象提供的功能。这样在活动中就可以指挥服务了,也就实现了活动与服务通信。
实例:希望在MyService里提供一个下载功能,然后在活动中可以决定何时开始下载,以及随时查看下载进度。
MyService代码如下:

public class MyService extends Service {

    //new一个DownloadBinder实例
    private DownloadBinder mBinder = new DownloadBinder();

    //创建一个DownloadBinder提供开始下载和获取进度两个方法
    class DownloadBinder extends Binder{
        public void startDownload() {
            //开始下载
            Log.d("MyService", "startDownload executed");
        }

        public int getProgress() {
            //获取进度
            Log.d("MyService", "getProgress executed");
            return 0;
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        //返回DownloadBinder实例
        return mBinder;
    }
}

可以看到,首先专门创建了一个DownloadBinder类继承Binder,然后在它的内部提供了开始下载以及查看下载进度的方法。当然这只是两个模拟方法,并没有实现真正的功能,在这两个方法中分别打印了一行日志。接着,在MyService中创建了DownloadBinder的实例,然后在onBind()方法里返回了这个实例,这个实例将会被传到后面的ServiceConnection中的onServiceConnection()方法中。
假设已经在MainActivity的布局文件activity_main.xml中添加了2个按钮。
MainActivity代码如下:

public class MainActivity extends Activity implements View.OnClickListener {

    private Button bind;
    private Button unbind;
    //声明一个MyService.DownloadBinder的实例
    private MyService.DownloadBinder downloadBinder;
    //创建ServiceConnection的实例connection,并实现ServiceConnection
    private ServiceConnection connection=new ServiceConnection() {
        //连接上服务时运行该方法
        //其中IBinder service是从Service中onBind()方法中返回的
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //获取DownloadBinder实例
            downloadBinder = (MyService.DownloadBinder) service;
            //调用执行开始下载和获得进程这两个方法
            downloadBinder.startDownload();
            downloadBinder.getProgress();
        }

        //与服务断开连接时运行该方法
        @Override
        public void onServiceDisconnected(ComponentName name) {
            //执行一些收尾的工作
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bind = (Button) findViewById(R.id.bind);
        unbind = (Button) findViewById(R.id.unbind);
        bind.setOnClickListener(this);
        unbind.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bind:
                //创建指向MyService的Intent实例
                Intent bindIntent = new Intent(this, MyService.class);
                //绑定服务
                bindService(bindIntent, connection, BIND_AUTO_CREATE);
                break;
            case R.id.unbind:
                //解绑服务
                unbindService(connection);
                break;
        }
    }
}

可以看到,这里首先创建了一个ServiceConnection的匿名类,在里面重写了onServiceConnected()方法和 onServiceDisconnected()方法,这两个方法分别会在活动与服务成功绑定以及解除绑定的时候调用。在onServiceConnected()方法中,通过向下转型得到了DownloadBinder的实例,有了这个实例,活动和服务之间的关系就变得非常紧密了。
现在可以在活动中根据具体的场景来调用DownloadBinder中的任何public方法,即实现了指挥服务干什么,服务就去干什么的功能。这里仍然只是做了个简单的测试,在onServiceConnected()方法中调用了DownloadBinder的startDownload()和getProgress()方法。当然,现在活动和服务其实还没进行绑定呢,这个功能是在bind按钮的点击事件里完成的。可以看到,这里是构建出了一个Intent对象,然后调用bindService()方法将MainActivity和MyService 进行绑定。bindService()方法接收三个参数,第一个参数就是刚刚构建出的Intent对象,第二个参数是前面创建出的ServiceConnection的实例,第三个参数则是一个标志位,这里传入BIND_AUTO_CREATE表示在活动和服务进行绑定后自动创建服务。这会使得MyService中的onCreate()方法得到执行,但onStartCommand()方法不会执行。
然后如果想解除活动和服务之间的绑定只要调用一下unbindService()方法就可以了,这也是unbind按钮的点击事件里实现的功能。
另外需要注意,任何一个服务在整个应用程序范围内都是通用的,即MyService不仅可以和MainActivity绑定,还可以和任何一个其他的活动进行绑定,而且在绑定完成后它们都可以获取到相同的DownloadBinder实例。


作者:lj2012sy
来源:CSDN
原文:https://blog.csdn.net/lj2012sy/article/details/51679564
版权声明:本文为博主原创文章,转载请附上博文链接!

发表评论

邮箱地址不会被公开。 必填项已用*标注