zoukankan      html  css  js  c++  java
  • android开发之service详解

    service作为android的四大组件之一,其重要性可想而知,在开发中,我们经常把一些不需要与用户进行交互的工作放在service中来完成,service运行在后台,这样有些人可能会产生错觉,以为service是运行在新线程中,其实不然,service也运行在主线程中,因此不能在service中进行耗时操作,否则会报ANR异常,但是我们可以在service中新开线程来进行耗时操作,比如下载等等。

    先来说说service的两种绑定方式,一种是通过Context.startService()来启动,另一种是绑定的方式,通过bindService方法来实现。

    第一种启动方式:我们一般在onStart()方法中启动service(使用方法startService()或者bindService()),在onStop方法中停止service(使用方法stopService()或者unbindService())。


    先来看看第一种:


    public class MyService1 extends Service {
    
        @Override
        public void onCreate() {
            Log.i("lenve", "onCreate()");
            sendMsg2Activity("服务创建");
        }
        //废弃的方法,不再使用
        @Override
        public void onStart(Intent intent, int startId) {
            super.onStart(intent, startId); 
            Log.i("lenve", "onStart()");
        }
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.i("lenve", "onStartCommand()");
            return super.onStartCommand(intent, flags, startId);
        }
    
        private void sendMsg2Activity(String string) {
            Intent intent = new Intent("service2activity");
            intent.putExtra("msg", string);
            this.sendBroadcast(intent);
        }
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.i("lenve", "onDestroy()");
        }
        @Override
        public IBinder onBind(Intent intent) {
            Log.i("lenve", "onBind()");
            return null;
        }
    
    }

    在Activity中启动Service

    intent = new Intent(this, MyService1.class);
    startService(intent);

    停止service

    stopService(intent);

    通过打印日志我们可以发现,第一次调用service时会触发onCreate()方法,后面的调用则不会再执行onCreate()方法,无论我们启动了多少次Service,它都只有一个,即停止service只需执行一次即可。


    第二种,通过绑定的方式启动service


    如果要细分的话这种启动方式又分为两种:
    1.设计接口,通过Ibinder实现接口来对Activity暴露方法供其调用。
    接口:

    public interface MyServiceInterface {
    
        public int add(int a,int b);
    }

    MyService.java

    public class MyService1 extends Service {
    
        private IBinder myBinder = new MyBinder();
        public class MyBinder extends Binder implements MyServiceInterface{
    
            @Override
            public int add(int a, int b) {
                return a+b;
            }
    
        }
        @Override
        public IBinder onBind(Intent intent) {
            Log.i("lenve", "onBind()");
            return myBinder;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            Log.i("lenve", "onCreate()");
            myBinder = new MyBinder();
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.i("lenve", "onDestroy()");
        }
    
        @Override
        public boolean onUnbind(Intent intent) {
            Log.i("lenve", "onUnbind()");
            return super.onUnbind(intent);
        }
    
        @Override
        public void onRebind(Intent intent) {
            super.onRebind(intent);
            Log.i("lenve", "onRebind()");
        }
    
    }

    在activity中启动service并调用add方法:

    public class MainActivity extends Activity {
    
        private TextView tv1;
        private ServiceConnection conn;
        private Intent intent;
        private MyServiceInterface msi;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            tv1 = (TextView) this.findViewById(R.id.textView1);
            intent = new Intent(this, MyService1.class);
            Log.i("lenve", "" + 1);
            conn = new ServiceConnection() {
    
                // 连接中断时调用
                @Override
                public void onServiceDisconnected(ComponentName name) {
                }
    
                // 连接成功时调用
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    msi = (MyServiceInterface) service;
                    Log.i("lenve", "连接成功!");
                }
            };
            bindService(intent, conn, BIND_AUTO_CREATE);
        }
    
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.button1:
                tv1.setText(msi.add(4, 5) + "");
                break;
    
            default:
                break;
            }
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            unbindService(conn);
        }
    }

    我们通过接口,可以在Activity中调用service中的方法,这样便实现了两者之间的通信。

    2.在onBinder()中返回Binder,而在继承Binder的类中直接返回当前service对象,通过该service对象来调用service中公开的方法。

    service代码

    public class MyService2 extends Service {
    
        private IBinder myBinder = new MyBinder();
    
        public class MyBinder extends Binder {
            public MyService2 getService() {
                return MyService2.this;
            }
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            Log.i("lenve", "onBind()");
            return myBinder;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            Log.i("lenve", "onCreate()");
            myBinder = new MyBinder();
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.i("lenve", "onDestroy()");
        }
    
        @Override
        public boolean onUnbind(Intent intent) {
            Log.i("lenve", "onUnbind()");
            return super.onUnbind(intent);
        }
    
        @Override
        public void onRebind(Intent intent) {
            super.onRebind(intent);
            Log.i("lenve", "onRebind()");
        }
    
        public int minus(int a, int b) {
            return a - b;
        }
    }

    activity中绑定:

    public class MainActivity extends Activity {
    
        private TextView tv1;
        private ServiceConnection conn;
        private Intent intent;
        private MyService2 ms2;
        private MyServiceInterface msi;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            tv1 = (TextView) this.findViewById(R.id.textView1);
    //      intent = new Intent(this, MyService1.class);
            intent = new Intent(this, MyService2.class);
            conn = new ServiceConnection() {
    
                // 连接中断时调用
                @Override
                public void onServiceDisconnected(ComponentName name) {
                }
    
                // 连接成功时调用
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
    //              msi = (MyServiceInterface) service;
                    //拿到当前service对象
                    MyBinder mb = (MyBinder) service;
                    ms2 = mb.getService();
                    Log.i("lenve", "连接成功!");
                }
            };
            bindService(intent, conn, BIND_AUTO_CREATE);
    //      new Thread(new Runnable() {
    //
    //          @Override
    //          public void run() {
    //              try {
    //                  Thread.sleep(2000);
    //                  tv1.setText(msi.add(4, 5)+"");
    //              } catch (InterruptedException e) {
    //                  e.printStackTrace();
    //              }
    //          }
    //      }).start();
        }
    
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.button1:
                //直接调用service中的public方法
                tv1.setText(ms2.minus(9, 6)+"");
    //          tv1.setText(msi.add(4, 5) + "");
    
                break;
    
            default:
                break;
            }
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            unbindService(conn);
        }
    }

    个人觉得第二种方式更好,不仅省事,而且交互也比较方便。

    其实,如果想实现service和activity之间的通信还可以使用broadcast。

    更高深的aidl我们下回分解。

    本示例代码下载http://pan.baidu.com/s/1sjupRZZ

    版权声明:本文为博主原创文章,未经博主允许不得转载。若有错误地方,还望批评指正,不胜感激。

  • 相关阅读:
    JUC-狂神笔记整理学习
    多线程-学习笔记
    Redis分布锁
    Redis
    springcloud一个简单的基本流程
    Nacos
    mysql单表查询
    mysql多表查询
    mysql数据库
    mysql详细安装教程以及1067错误代码解决方案
  • 原文地址:https://www.cnblogs.com/lenve/p/4770539.html
Copyright © 2011-2022 走看看