最简单的Activity、Service使用、通信指南一(进程内通信)(附github源码)

本篇是要介绍activity和service的通信的使用,通过一个小例子实现了activity获取service的数据并展示。

我们知道activity和service(默认)都是在一个进程和主线程里面,这篇主要是介绍同一进程的activity和service的通信。聪明的你肯定知道了不同进程的activity和service的通信实现会有差别。

【转载请注明出处:最简单的Activity、Service使用、通信指南一(进程内通信)(附github源码) CSDN 王智博

源码下载

github:https://github.com/samwangzhibo/LoveStudy (不会使用github导入代码的同学,戳这)

先看效果:

先点击按钮,开启并让activity连接service,然后service开启一个线程,它的一个成员变量每秒增加1,然后点击按钮获取service的数据并展示到activity。

大体思路

1.实现一个service,并且在service里面开启一个线程,里面有num变量一秒递增一次。

2.service定义binder对象,通过binder对象,返回num变量

3.activity先开启service并且获取service返回的集成Ibinder的binder对象,取出binder对象中的num值,展示在页面上

4.activity销毁的时候,关闭service线程并解绑service

1.创建线程,里面有num变量一秒递增一次。

class SendThread extends Thread {
        int num = 0;
        boolean isEnd = false;
        private final int DURATION_SLEEP = 1000;

        /**
         * 关闭线程
         * @param end
         */
        void setEnd(boolean end) {
            isEnd = end;
        }

        public int getNum(){
            return num;
        }

        @Override
        public void run() {
            super.run();
            while (!isEnd) {
                num++;
                try {
                    //不释放资源 休眠
                    Thread.sleep(DURATION_SLEEP);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

2.service定义binder对象,通过binder对象,返回num变量 

public class MathService extends Service {
    ...
    @Override
    public IBinder onBind(Intent intent) {
        return new MathBinder();
    }
    
    public class MathBinder extends Binder{
        //返回service
        public MathService getService(){
            return MathService.this;
        }
    }

    //获取线程的num
    public int getNum(){
        return thread.getNum();
    }
    ...
}

定义一个Sercive,onbind方法返回MathBinder对象,MathBinder对象可以获取Service,Service中有个getNum()方法,可以获取线程的num值

3.activity绑定service,获取binder对象,通过binder对象获取service和num值

3.1绑定service

Intent intent = new Intent(MainActivity.this, MathService.class);
                    bindService(intent, this, BIND_AUTO_CREATE);

3.2获取binder

上步中有个boolean bindService(Intent service, ServiceConnection conn, int flags) 方法,其中第二个参数是一个ServiceConnection回调,我们实现它的void onServiceConnected(ComponentName name, IBinder service)方法,其中service参数就是我们在service中onBind()方法设置的MathBinder对象

public void onServiceConnected(ComponentName name, IBinder service) {
        mathService = ((MathService.MathBinder) service).getService();
    }

获取num的值并展示

commuteWithServiceBtn.setText("获取service数据 : " + mathService.getNum());

4.activity销毁的时候,关闭service线程并解绑service

protected void onDestroy() {
        super.onDestroy();
        unbindService(this);
        mathService.release();
    }

总结

activity通过bindService方式启动Service,通过onServiceConnection回调可以获取IBinder对象。这个对象是Service的onbind()方法返回的,所以我们只需要定义一个返回num对象的binder对象,在service的onbind()方法中返回即可。

源码下载

github:https://github.com/samwangzhibo/LoveStudy (不会使用github导入代码的同学,戳这)

扩展

如果把service设置到其他进程,跨进程的条件下,这种方法还适用吗?

我们在AndroidManifest.xml中添加process属性,设置service在:MathService进程

然后可以看到报错说不能把BinderProxy转成MathBinder ,我们找一下代码

也就是在多进程的环境下,这个 service对象不再是 我们onbind()里面返回的MathBinder

那么在跨进程情况下,我们该怎么来和service交互呢?

请看  最简单的Activity、Service使用指南二(进程间通信)(附github源码)

全部代码

public class MainActivity extends Activity implements View.OnClickListener, ServiceConnection{
    MathService mathService;
    Button commuteWithServiceBtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.btn_goto_handler_act).setOnClickListener(this);
        commuteWithServiceBtn = findViewById(R.id.btn_commute_with_service);
        commuteWithServiceBtn.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.btn_goto_handler_act:
                    startActivity(new Intent(MainActivity.this, HandlerActivity.class));
                    break;
            case R.id.btn_commute_with_service:
                if (mathService == null) {
                    //开启service
                    Intent intent = new Intent(MainActivity.this, MathService.class);
                    bindService(intent, this, BIND_AUTO_CREATE);
                    commuteWithServiceBtn.setText("连接成功,点击获取service数据");
                }else {
                    commuteWithServiceBtn.setText("获取service数据 : " + mathService.getNum());
                }
                break;
        }
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(this);
        mathService.release();
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        mathService = ((MathService.MathBinder) service).getService();
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        mathService = null;
    }
}
public class MathService extends Service {
    SendThread thread;
    public MathService() {
    }

    @Override
    public void onCreate() {
        thread = new SendThread();
        thread.start();
    }

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

    public class MathBinder extends Binder{
        //返回service
        public MathService getService(){
            return MathService.this;
        }
    }

    //获取线程的num
    public int getNum(){
        return thread.getNum();
    }

    public void release() {
        thread.setEnd(true);
    }

    class SendThread extends Thread {
        int num = 0;
        boolean isEnd = false;
        private final int DURATION_SLEEP = 1000;

        /**
         * 关闭线程
         * @param end
         */
        void setEnd(boolean end) {
            isEnd = end;
        }

        public int getNum(){
            return num;
        }

        @Override
        public void run() {
            super.run();
            while (!isEnd) {
                num++;
                try {
                    //不释放资源 休眠
                    Thread.sleep(DURATION_SLEEP);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/wangzhibo666/article/details/86606603
今日推荐