关于Service中bindService注意的几个问题

最近有用到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,即包名、类名)。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-25 19:21:12

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

Android中bindService的使用及Service生命周期

Android中有两种主要方式使用Service,通过调用Context的startService方法或调用Context的bindService方法,本文只探讨纯bindService的使用,不涉及任何startService方法调用的情况.如果想了解startService相关的使用,请参见<Android中startService的使用及Service生命周期>. bindService启动服务的特点 相比于用startService启动的Service,bindService启动的服务

Android中Service使用bindService

前面已经对Service的startServer方式启动一个服务了解过了,现在来看一下Service的另一种启动方式→bindServer bindServer使用场景 1.在同个app之间调用(即是同一个进程中) 2.在不同app之间调用(即是跨进程间通信) 同个app间调用(只有一次启动该服务) BinderActicityA public class BinderActicityA extends Activity implements View.OnClickListener { pri

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

原文网址:http://www.cnblogs.com/onlylittlegod/archive/2011/05/15/2046652.html 最近学习了一下Android里面的Service的应用,在BindService部分小卡了一下,主要是开始没有彻底理解为什么要这么实现. BindService和Started Service都是Service,有什么地方不一样呢: 1. Started Service中使用StartService()方法来进行方法的调用,调用者和服务之间没有联系,

Android中BindService方式使用的理解

Android中BindService方式使用的理解 - 唯一小神 - 博客园 最近学习了一下Android里面的Service的应用,在BindService部分小卡了一下,主要是开始没有彻底理解为什么要这么实现. BindService和Started Service都是Service,有什么地方不一样呢: 1. Started Service中使用StartService()方法来进行方法的调用,调用者和服务之间没有联系,即使调用者退出了,服务依然在进行[onCreate()-? >onS

Service中事务不能回滚的解决方式(转)

1.在service方法里面如果对异常进行了捕获的话,该事务是不会进行回滚的        默认spring事务只在发生未被捕获的 runtimeexcetpion时才回滚.          spring aop  异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚,默认情况下aop只捕获runtimeexception的异常,但可以通过配置来捕获特定的异常并回滚,换句话说在service的方法中不使用try catch 或者在catc

如何在Service中更新Activity的UI?

============问题描述============ 如何在Service中更新Activity的UI? 不想用广播.  有人说用接口,具体如何实现我一直不懂? 请赐教. ============解决方案1============ 将activity 实例传过来不就OK 了?然后调用其方法更新UI ============解决方案2============ 一般都用广播,否则在Activity也创建一个Messenger,也就是AIDL方式通信. ============解决方案3=====

ionic中将service中异步返回的数据赋值给controller的$scope

1.service中异步获取数据实例 angular.module('starter.services', []) .factory('Chats', function($http,$q) {//定义Chats的service return { all: function() {//all方法异步获取数据 var deferred=$q.defer(); //定义deferred var promise=deferred.promise;//定义promise $http.get('http:/

在Oracle/SQL Service中通过Function返回Table

本函数用途:返回一个Table 在Oracle中实现,范例: 1 --在Types中: 2 create or replace type objTable as object 3 ( 4 s_usercode varchar2(32767), 5 s_username varchar2(32767) 6 ); 7 8 CREATE OR REPLACE TYPE tabTemp AS TABLE OF objtable; 9 10 11 --在Function中: 12 --使用Pipeline

[Android Pro] service中显示一个dialog 或者通过windowmanage显示view

转载: http://blog.csdn.net/huxueyan521/article/details/8954844 通过windowmananger来在窗口上添加view的时候,需要设置alert参数,而且要添加alert权限 mLayoutParams = new WindowManager.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, LayoutParams.TYPE_SYSTEM_ALERT,