最近有用到Activity需要不断的从Service中获取数据,第一个想法肯定就是通过bind回调机制了,有几点概念模糊特此记录下:

单独使用bindService(),unbindService()会经历:->onCreate()->onBind()->Service running->onUnbind()
-> onDestroy() 。

单独使用startService(),stopService()会经历:->onCreate()->onStartCommand()->Service running-> onDestroy() 。

先调用startService(),再调用bindService()方法:

  • 如果结束只调用unbindService(),那么只会执行到onUnbind(),将不会执行onDestroy():->onCreate()->onStartCommand()->onBind()->Service
    running-> onUnbind()。
  • 如果在unbindService后,在调用stopService(),那么:->onCreate()->onStartCommand()->onBind()->Service running->
    onUnbind()->onDestroy() 。
1、绑定的Service只有当应用组件绑定后才能运行,多个组件可以绑定一个Service,当调用unbind()方法时,这个service就会被销毁了。
2、Service与Activity一样都存在与当前进程的主线程中,所以,一些阻塞UI的操作,比如耗时操作不能放在service里进行,比如另外开启一个线程来处理诸如网络请求的耗时操作。如果在service里进行一些耗CPU和耗时操作,可能会引发ANR警告,这时应用会弹出是强制关闭还是等待的对话框。所以,对service的理解就是和activity平级的,只不过是看不见的,在后台运行的一个组件,这也是为什么和activity同被说为Android的基本组件。
3、图形理解Service:

通过这个图可以看到,两种启动Service的方式以及他们的生命周期,bindService的不同之处在于当绑定的组件销毁后,对应的Service也就被kill了。Service的声明周期相比与Activity的简单了许多,只要好好理解两种启动service方式的异同就行

4、关于停止Service,如果service是非绑定的,最终当任务完成时,为了节省系统资源,一定要停止service,可以通过stopSelf()来停止,也可以在其他组件中通过stopService()来停止,绑定的service可以通过onUnBind()来停止service。

关于Activity与Service数据的互相传递,写了个demo:

public class MainActivity extends Activity implements View.OnClickListener {
    private  TextView mTextView;
    private EditText mEditText;
    private MyService.LocalBinder binder=null;
    MyService myService;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mEditText = (EditText) findViewById(R.id.edt_content);
        Button mBtnStart = (Button) findViewById(R.id.btn_start);
        Button mBtnClose = (Button) findViewById(R.id.btn_close);
        Button mBtnSubmit = (Button) findViewById(R.id.btn_submit);
        mTextView = (TextView) findViewById(R.id.tv_show);
        mBtnStart.setOnClickListener(this);
        mBtnClose.setOnClickListener(this);
        mBtnSubmit.setOnClickListener(this);
    }
    public ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            binder = (MyService.LocalBinder) service;//得到LocalBinder实例
            myService = binder.getService();//得到Service实例
            //设置接口回调获取Service中的数据
            myService.setOnDataCallback(new MyService.OnDataCallback() {
                @Override
                public void onDataChange( final String message) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mTextView.setText(message);
                        }
                    });
                }
            });
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            myService = null;
        }
    };
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(this,MyService.class);
        switch (v.getId()){
            case R.id.btn_start:
//                startService(intent);
                bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);//为Activity绑定服务
                break;
            case R.id.btn_close:
                unbindService(mServiceConnection);//解除绑定
//                stopService(intent);
                break;
            case R.id.btn_submit:
                if(binder!=null){
                    //把数据传给Service,相比用Bundle效率更高
                    binder.setData(mEditText.getText().toString());
                }
                break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mServiceConnection);//解除绑定
    }
}

MyService:

public class MyService extends Service {
    private String message ;
    private boolean isRunning = true;
    private IBinder binder = new LocalBinder();
    public class LocalBinder extends Binder {
        public void setData(String message) {
            //从Activity传入message值
            MyService.this.message = message;
        }

        public MyService getService() {
            //返回当前MyService对象
            return MyService.this;
        }
    }
    private OnDataCallback mOnDataCallback=null;

    public void setOnDataCallback(OnDataCallback mOnDataCallback) {
        this.mOnDataCallback = mOnDataCallback;
    }

    public interface OnDataCallback{
        void onDataChange(String message);
    }
    @Override
    public IBinder onBind(Intent intent) {
        //返回这个LocalBinder对象,其实这个对象可以在Activity中onServiceConnected()方法中接收到,这个bind就是Activity和Service通信的桥梁
        //因为在Activity通过这个bind对象可以得到Service的实例引用。一旦Service对象找到,就能得到它的公共方法和属性。
        return binder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        new Thread() {
            @Override
            public void run() {
                int i=1;
                while (isRunning) {
                    if(mOnDataCallback!=null){
                        mOnDataCallback.onDataChange(message + i);
                    }
                    i++;
                    try {
                        sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        isRunning = false;
    }
}

Activity能进行绑定得益于Service的接口onBind()。Service和Activity的连接可以用ServiceConnection来实现,需要实现一个新的ServiceConnection,重写onServiceConnected和onServiceDisconnected方法。执行绑定,调用bindService方法,传入一个选择了要绑定的Service的Intent(显式或隐式)和一个你实现了的ServiceConnection实例。一旦连接建立,你就能通Service的接口onBind()得到mBinder实例进而得到Service的实例引用。一旦Service对象找到,就能得到它的公共方法和属性。但这种方式,只能在同一个进程和同一个Application里。跨进程跨应用通信IPC需要建立aidl文件(注:Android5.0以后跨应用只能通过显示Intent来启动Service,即包名、类名)。

关于Service中bindService注意的几个问题的更多相关文章

  1. 【转】Android中BindService方式使用的理解

    原文网址:http://www.cnblogs.com/onlylittlegod/archive/2011/05/15/2046652.html 最近学习了一下Android里面的Service的应 ...

  2. Service 中的 onStart 和 onStartCommand

    在自定义的service中,写了onStart和onStartCommand, public class HttpWebService extends Service { @Override publ ...

  3. android中activity向service中传值

    和activity中互相传值类似 在activity中 Intent regIntent = new Intent(this, ChatService.class);  regIntent.putEx ...

  4. Android系统编程入门系列之服务Service中的进程间通信

    在上篇文章以线程间的通信方式Handler类结尾,服务Service还支持的进程间通信,又是具体怎么实现的呢?这就要用到加载服务一文中提到的AIDL语言规范了. AIDL是 Android Inter ...

  5. 如何托管ASP.NET Core应用到Windows Service中

    (此文章同时发表在本人微信公众号"dotNET开发经验谈",欢迎右边二维码来关注.) 题记:正在构思一个中间件的设计,考虑是否既可以使用最新的技术,也可以兼顾传统的部署模式.所以有 ...

  6. Web Service 中返回DataSet结果大小改进

    http://www.cnblogs.com/scottckt/archive/2012/11/10/2764496.html Web Service 中返回DataSet结果方法: 1)直接返回Da ...

  7. 跟我学Windows Azure 四 Cloud Service中的WebRole与WorkRole,及他们之间的通信

    Cloud Service 中WebRole就相当与我们的WebSite,而WorkRole相当与我们在服务器上写了个Windows Service,站在高可用的角度上来讲,Cloud Service ...

  8. JAVA CDI 学习(5) - 如何向RESTFul Service中注入EJB实例

    RESTFul Service中如果要注入EJB实例,常规的@Inject将不起作用,在Jboss中,应用甚至都启动不起来(因为@Inject注入失败),解决方法很简单:将@Inject换成@EJB ...

  9. (原创)在service中定时执行网络操作的几点说明

    执行网络操作是耗时操作,即便是在service中也要放到子线程中执行 这里我用到了async-http-client框架来执行异步请求操作 计时用的java原生Timer和TimerTask类 本来这 ...

随机推荐

  1. MacOS获取辅助功能权限控制鼠标点击事件

    昨晚玩一个模拟经营的游戏,由于升级太慢我就不停的种树卖树来换取经验值.不过重复点击10几分钟后,实在受不了.网上本来准备找个鼠标自动点击的软件用用.结果没找到趁手的.如是自己写了个. 自己设置需要点击 ...

  2. LuaHotUpdate原理

    LuaHotUpdate原理(金庆的专栏)项目地址:https://github.com/asqbtcupid/lua_hotupdate只更新函数,不更新数据.主页上有个动画演示.限Windows平 ...

  3. Linux 高性能服务器编程——Linux服务器程序规范

    问题聚焦:     除了网络通信外,服务器程序通常还必须考虑许多其他细节问题,这些细节问题涉及面逛且零碎,而且基本上是模板式的,所以称之为服务器程序规范.     工欲善其事,必先利其器,这篇主要来探 ...

  4. 深入浅出如何解析xml文件---下篇

    在上篇博文中,小编主要介绍xml的两种解析方式,分别是dom4j和dom,今天这篇博文,小编主要来简单介绍一下xml的其她两种解析方式sax和jdom.  sax解析xml文件 sax,全称是Simp ...

  5. linux添加环境变量(path)

    分为三步 1.sudo vim /etc/profile 2.export PATH="全路径:$PATH" 3.source /etc/profile 我的微信二维码如下,欢迎交 ...

  6. 剑指Offer——咪咕笔试题+知识点总结

    剑指Offer--咪咕笔试题+知识点总结 情景回顾 时间:2016.10.09 15:00-16:30 地点:山东省网络环境智能计算技术重点实验室 事件:咪咕笔试 知识点总结 1.Html设置格式贵阳 ...

  7. Java HashMap并发死循环

    在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环.这个事情我4. ...

  8. OpenMP基础----以图像处理中的问题为例

        OpenMP2.5规范中,对于可以多线程执行的循环有如下5点约束: 1.循环语句中的循环变量必须是有符号整形,如果是无符号整形就无法使用,OpenMP3.0中取消了这个约束 2.循环语句中的比 ...

  9. android打包引用第三方jar出现的错误

    今天终于完成了近一个月的App开发工作,对程序进行混淆导出签名apk包时,却出现了如下的错误: Proguard returned with error code 1. See console Not ...

  10. 如何在Cocos2D游戏中实现A*寻路算法(六)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...