zoukankan      html  css  js  c++  java
  • Service启动和数据传递

    Service是四大组件之一,Service是服务的意思,像Windows上面的服务一样,服务是在后台运行的,承担着静悄悄,默默的在后台付出的工作。

    在开发过程中Service可以在很多地方使用,比如播放多媒体的时候用户启动了其他Activity ,这个时候程序要在后台继续播放;或者在后台记录用户地理位置的改变,或者启动服务来一直监听某种事件等。虽然Service存在的价值不如Activity,但是一般都让Service执行耗时时间较长的操作。下面我们详细介绍一下Service。

    一,启动Service主要有两种方式:

      1)  startService(),调用者与服务之间没有关联,即时调用者退出,服务仍然可以运行。

        被启动的服务是由调用startService方法启动的,该方法会调用生命周期方法onStartComment(),当服务被启动后,改服务的生命周期与其他组件没有关系,即使启动服务的组件(Activity,BroadcastReciver)已经被销毁,该服务还是可以在后台无限期的运行,除非调用stopService()来停止服务。

          2)  bindService(),调用者与服务绑定在一起,调用者一旦退出(启动Service的Activity退出,Service也退出),服务也退出。

        绑定服务是调用bindService方法启动的,绑定调用了onBind生命周期方法,改方法返回IBinder对象,同时启动服务的Activity必须提供ServiceConnect接口的实现类,它有两个方法onServiceConnected和onServiceDisconnected方法,监听Activity与服务类之间的连接。

    二,Service的生命周期:

      

    1、Started Service的生命周期:
    • onCreate():创建服务
    • onStartCommand():服务开始运行(在2.0以前版本中,使用onStart()回调方法)
    • onDestroy() :服务被停止
    【详细说明:】
    • 在程序中调用:context.startService() 会触发执行Service生命周期中的onCreate()、onStartCommand()回调方法,此时服务就开始正式运行;
    • 如果Service还没有运行,则android先调用onCreate()然后调用onStartCommand();如果Service已经运行,则只调用onStartCommand(),所以一个Service的onStartCommand方法可能会重复调用多次;
    • 如果在程序中调用:context.stopService()会触发执行Service生命周期中的onDestroy()回调方法,会让服务停止;
    • stopService()的时候直接onDestroy,如果是调用者自己直接退出而没有调用stopService()的话,Service会一直在后台运行。该Service的调用者再启动该Service后可以通过stopService关闭Service;
    • 所以StartService的生命周期为:onCreate --> onStartCommand(可多次调用) --> onDestroy。
     
    2、Bound Service的生命周期:
    • onCreate():创建服务
    • onBind():绑定服务,服务开始运行
    • onUnbind():取消绑定
    • onDestroy() :服务被停止
    【详细说明:】
    • 在程序中调用:context.bindService()会触发执行Service生命周期中的onCreate()、onBind()回调方法,此时服务开始运行;
    • onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。此后调用者(Context,例如Activity)会和Service绑定在一起;
    • 如果调用Service的调用者Context退出了,那么会依次调用Service生命周期中的onUnbind()、onDestroy()回调方法,会让服务停止;    
    • 所以BindService的生命周期为:onCreate --> onBind(只一次,不可多次绑定) --> onUnbind --> onDestory。

    三,绑定Service通信:

      1,向Service内部传递数据:

         创建一个Activity,用来启动Service,我们在Activity里面创建一个布局,如下所示:

          

       EditText用来动态改变向Service里面数据,点击同步数据按钮用来将Activity里面的数据传递到Service里面。

       将数据同步到Service里面需要利用服务得IBinder对象。下面是我的服务类:

    public class MyService extends Service {
    
        private boolean running = false;
        private String data = "默认信息";//创建一个字符串,用来接收数据
    
        public MyService() {
        }
    
        @Override
        public IBinder onBind(Intent intent) {
        
    return new Binder();//④返回Binder的事例 } /** *②创建一个类继承Binder,来对data数据进行更新 */ public class Binder extends android.os.Binder{ public void setData(String data){//③写一个公共方法,用来对data数据赋值。 MyService.this.data = data; } } @Override public void onCreate() { super.onCreate(); running = true; new Thread(){ //①创建一个Thread用来数据传递进来的data数据。 @Override public void run() { super.run(); while (running){ System.out.println(data);//打印数据 try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } @Override public void onDestroy() { super.onDestroy(); running = false; }

    在Activity中,需要实现ServiceConnection接口,并且在绑定成功的onServiceConnected方法中初始化Binder对象:

    1,首先定义变量 private MyService.Binder binder = null;

    2,在onServiceConnected方法中进行初始化:

    @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            binder = (MyService.Binder) service;
        }

    3,点击同步数据按钮向Service里面赋值:

      binder.setData(editText.getText().toString());

    具体代码如下所示:

    public class MainActivity extends AppCompatActivity implements OnClickListener, ServiceConnection {
        private EditText editText;
        private MyService.Binder binder = null;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.content_main);
            editText = (EditText) findViewById(R.id.edit);
            findViewById(R.id.bindService).setOnClickListener(this);
            findViewById(R.id.unbindService).setOnClickListener(this);
            findViewById(R.id.btnSync).setOnClickListener(this);
        }
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.bindService://点击绑定服务按钮
                    bindService(new Intent(this,MyService.class),this, Context.BIND_AUTO_CREATE);
                    break;
                case R.id.unbindService://解除绑定服务按钮
                    unbindService(this);
                    break;
                case R.id.btnSync://同步数据按钮
                    if (binder != null){
                        binder.setData(editText.getText().toString());
                    }
                    break;
            }
        }
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            binder = (MyService.Binder) service;
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
    
        }
    }
    View Code

    这样就完成了想Service内部的数据传递。

    四,service向Activity传递数据

     上面介绍了Activity向Service内部传值,现在我们来介绍一下Service向Activity传递数据:

     从Service向Activity传值,我们需要利用接口,首先在MyService里面自定义一个接口CallBack,实现onDataChanged方法;  

     public static  interface  CallBack{
             void onDataChanged(String data);
        }

    在MyService里面定义CallBack类型的变量,并且实现它的set方法,来获得CallBack的实例。在MyService的Oncrate方法中定义一个变量i,然后动态改变i的数值,然后通过callback.onDataChanged("数据="+i) 将数据进行传递。具体实现方法如下所示:

    public class MyService extends Service {
    
        private boolean running = false;
    
        public MyService() {
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return new Binder();
        }
    
        /**
         *创建一个类继承Binder,来进行
         */
        public class Binder extends android.os.Binder{
            public MyService getService(){
                return MyService.this;
            }
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            running = true;
            new Thread(){
                @Override
                public void run() {
                    super.run();
                    int i = 0;
                    while (running){
                        i++;
                        if (callback != null){
                            callback.onDataChanged("数据="+i);
                        }
                        try {
                            sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            running = false;
        }
    
        private CallBack callback = null;
    
        public void setCallback(CallBack callback) {
            this.callback = callback;
        }
    
        public static  interface  CallBack{
             void onDataChanged(String data);
        }
    }
    View Code

    在Activity中我们需要 1,获得Myservice的实例来调用serCallBack方法,所以我在MyService的Binder方法里面添加了获取MyService实例的方法。

    2,将调用CallBack接口之后onDataChanged方法返回的值赋值到TextView上面,还是用到了servce的IBinder对象。

    具体实现方法如下所示:

    public class MainActivity extends AppCompatActivity implements OnClickListener, ServiceConnection {
    
        private TextView textView;
        private MyService.Binder binder = null;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.content_main);
            textView = (TextView) findViewById(R.id.tvout);
            findViewById(R.id.bindService).setOnClickListener(this);
            findViewById(R.id.unbindService).setOnClickListener(this);
        }
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.bindService://点击绑定服务按钮
                    bindService(new Intent(this,MyService.class),this, Context.BIND_AUTO_CREATE);
                    break;
                case R.id.unbindService://解除绑定服务按钮
                    unbindService(this);
                    break;
            }
        }
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            binder = (MyService.Binder) service;
    
            binder.getService().setCallback(new MyService.CallBack() {
                @Override
                public void onDataChanged(String data) {//因为在Service里面赋值data是在Thread中进行的,所以我们不能直接在这里将返回的值展示在TextView上。
                    Message msg = new Message();
                    Bundle bundle = new Bundle();
                    bundle.putString("data",data);
                    msg.setData(bundle);
                    handler.sendMessage(msg);
                }
            });
        }
    
        @Override
        public void onServiceDisconnected(ComponentName name) {
    
        }
    
        Handler handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                textView.setText(msg.getData().getString("data"));
            }
        };
    }
    View Code

    源码地址:

    Activity向Service传递数据:http://download.csdn.net/detail/jingsummer/9372505

    Service里面的数据传递到Activity中:http://download.csdn.net/detail/jingsummer/9372513

          

  • 相关阅读:
    [Bzoj2243][SDOI2011]染色(线段树&&树剖||LCT)
    [poj3074]Sudoku(舞蹈链)
    [Bzoj1047][HAOI2007]理想的正方形(ST表)
    [Bzoj1030][JSOI2007]文本生成器(AC自动机&dp)
    [Bzoj2431][HAOI2009]逆序对数列(前缀和优化dp)
    [Bzoj1072][SCOI2007]排列perm(状压dp)
    [Bzoj1195][HNOI2006]最短母串(AC自动机)
    Ajax解决IE浏览器兼容问题
    运行eclipse弹出“Failed to load the JNI shared”解决方法
    Java表单类双击提交
  • 原文地址:https://www.cnblogs.com/blogljj/p/5067696.html
Copyright © 2011-2022 走看看