zoukankan      html  css  js  c++  java
  • Android 组件之Service解析

    原创文章,转载请注明 http://blog.csdn.net/leejizhou/article/details/50866875 李济洲的博客

    Service是Android四大组件之中的一个。Service主要作用于后台,能够进行一些后台的操作,它没实用户界面。它跟Activity比較类似,某种意义上能够理解为“Service是没实用户界面的Activity“,那么我们什么时候须要使用Service呢?比如:音乐App正在播放音乐我们想切换到阅读App又不想让音乐停止就会用到Service,音乐App正在下载音乐我们切换到桌面又不想让下载停止就会使用到Service。

    编写Activity须要两步:1:编写Activity的子类 2:在AndroidManifest.xml中配置此Activity,相同编写Service也须要两步:

    1:定义一个继承自Service的子类
    2:在AndroidManifest.xml中配置此Service

    startService

    我们先编写一个简单的StartService演示样例程序来演示怎样实现Android后台操作
    先定义一个Service的子类,然后复写一些生命周期函数

    /**
     * Blog:http://blog.csdn.net/leejizhou
     * 李济洲的博客
     */
    public class MyService extends Service {
    
        //Service中唯一的抽象方法。必须在子类中实现,用来和Activity通信。先返回NULL
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        //复写Service的一些生命周期函数
    
        //onCreate会在Service第一次创建的时候调用
        @Override
        public void onCreate() {
            super.onCreate();
            Log.d("MyService","----onCreate executed----");
        }
    
        //onStartCommand会在Service每次启动的时候调用
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.d("MyService","----onStartCommand----");
            return super.onStartCommand(intent, flags, startId);
        }
        //onDestroy会在Service销毁时候调用
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.d("MyService", "----onDestroy----");
        }
    }

    以下是Service的生命周期,为什么有两种呢?由于启动Servcie有两种方式第一个是startService()主要用于启动一个Service运行后台任务不进行通信,还有一个是bindService()是启动一个跟组件绑定的Service能够进行通信,先介绍的是startService()。

    这里写图片描写叙述

    然后在AndroidManifest.xml中进行配置此Service。千万不要忘记。

      <service android:name=".MyService"></service>

    定义好Service后,接下来就是启动和停止这个服务了。启动和停止主要靠Intent来实现,这里我定义了两个Button用来启动和停止。部分代码略(文章结尾会提供源代码),主要看下启动和停止Service的实现代码。

     //开启Service
            findViewById(R.id.StartService).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent=new Intent(MainActivity.this,MyService.class);
                    startService(intent);
                }
            });
     //停止Service
            findViewById(R.id.StopService).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent=new Intent(MainActivity.this,MyService.class);
                    stopService(intent);
                }
            });

    点击开启Service能够看到OnCreate和OnStartCommand被运行了,一个简单的后台Service就被启动了

    这里写图片描写叙述

    然后点击停止。能够看到OnDestroy被运行了

    这里写图片描写叙述

    这里可能你会问了。启动Service,OnCreate和OnStartCommand都被运行了,他俩有什么差别呢?onCreate会在Service第一次创建的时候调用,假设一个Service没有Stop再次启动这个Service的话是不会再调用onCreate方法了,可是每次OnStartCommand都会被调用。所以后台须要运行的代码逻辑我们一般须要放到OnStartCommand方法里面。

    这里写图片描写叙述

    Ok 在Activity里面启动一个简单的Service后台服务就完毕了,可是你要知道的是通过startService()启动这个服务后就和Activity就没有关系了,即使你这个Activity被销毁这个Service依旧会在后台运行。切记通过startService()启动服务任务结束后在Activity中调用 stopService()结束掉这个Service。或者在Servcie子类中调用stopSelf()来结束自己。

    上面介绍了startService启动服务,它能够很简单的启动后台Service进行一些逻辑操作,可是无法进行控制和通信,以下介绍下BindService能够解决问题。

    bindService

    以下实现一个后台Service进行数值的递增运算。Activity能够实时查看Service此时的数值的小演示样例来了解bindService的使用。

    定义Service。这里我们要实现onBind的方法。在这里onStartCommand无需复写,由于通过bindService启动服务是不回调此方法的。Service的onCreate里面进行的了一个循环的数值运算。

    /**
     * Blog:http://blog.csdn.net/leejizhou
     * 李济洲的博客
     */
    public class MyService extends Service {
    
        //当前数值
        private int num=0;
        //是否停止循环
        private boolean isgo=true;
    
        //BindService 须要实现onBind方法 自己定义一个Binder对象返回
        private MyBinder binder=new MyBinder();
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return binder;
        }
    
        public class MyBinder extends Binder{
             //建立一个方法用于返回当前数值
             public int getNum(){
                 return num;
             }
         }
    
        //Service创建时候回调此方法 这里定义一个循环 不断更改num的值
        @Override
        public void onCreate() {
            super.onCreate();
    
            //进行循环操作,每秒数值加1
           new Thread(new Runnable() {
               @Override
               public void run() {
                   while(isgo){
                       try {
                           Thread.sleep(1000);
                       } catch (InterruptedException e) {
                           e.printStackTrace();
                       }
    
                       num++;
                       Log.i("MyService",num+"");
                   }
    
               }
           }).start();
    
        }
    
        //这里不须要复写此方法。由于bindService启动服务不会调用此方法
    //    @Override
    //    public int onStartCommand(Intent intent, int flags, int startId) {
    //        return super.onStartCommand(intent, flags, startId);
    //    }
    
        //Service断开时回调此方法
        @Override
        public boolean onUnbind(Intent intent) {
            Log.i("MyService","----onUnbind----");
            return super.onUnbind(intent);
        }
        //Service销毁是回调此方法
        @Override
        public void onDestroy() {
            super.onDestroy();
            isgo=false;
            Log.i("MyService","----onDestroy----");
        }
    }
    

    然后再AndroidManifest.xml中配置服务,一定一定一定不要忘记。

     <service android:name=".MyService"></service>

    之后在Activity里面通过bindService启动服务,Activity里面三个button用来启动 停止 和获取数值

    /**
     * Blog:http://blog.csdn.net/leejizhou
     * 李济洲的博客
     */
    public class MainActivity extends AppCompatActivity {
        //获取Service中的Binder对象
        MyService.MyBinder binder;
        //定义一个ServiceConnection对象
        private ServiceConnection connection=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                //Activity与Service连接成功时候回调此方法
                binder=(MyService.MyBinder)service;
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                //Activity与Service断开连接时回调此方法,Activity主动调用unBindService将不掉用此方法。仅仅在异常终止时刻调用
                Log.i("MyService","----onServiceDisconnected-----");
            }
        };
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //启动Service
            findViewById(R.id.bindService).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent bindIntent=new Intent(MainActivity.this, MyService.class);
                    //这里第一个參数传入intent 第二个參数传入ServiceConnection对象
                    //第三个參数指Activity和Service绑定时是否创建服务。这里直接传BIND_AUTO_CREATE就好了。之后Service的onCreate会得到运行
                    bindService(bindIntent,connection, Service.BIND_AUTO_CREATE);
                }
            });
            //停止Service
            findViewById(R.id.UnBindService).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //解除绑定Service
                   unbindService(connection);
    
                }
            });
            //获取Service中此刻的数值
            findViewById(R.id.getnum).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(MainActivity.this,"Service的数值"+binder.getNum()+"",3000).show();
                }
            });
        }
    }
    

    bindService运行生命周期
    这里写图片描写叙述

    注意到Activity中ServiceConnection对象中的OnServiceConnected方法中有一个IBinder对象,该对象就可以实现Activity与Service之间的通信,使用bindService方式启动Service的时候,Service子类必须实现onBind方法,onBind方法返回的IBinder对象将会传递到onServiceConnected(ComponentName name, IBinder service)其中来实现通信交互。

    这样Activity和Service通信的小演示样例就完毕了,值得注意的是通过onBind方法启动Service,Service和Activity是绑定状态的。那么假设Activity被销毁Service也会跟着一起销毁这点要注意,要区分startService和bindService的差别。

    那么你可能会问假设我想让Service能够和Activity通信同一时候又能够不随Activity销毁该怎样做呢?仅仅须要 startService和bindService一起调用就能够了。假设同一时候调用了start和bind,那么调用unbindService将不会停止Service,而必须调用 stopService 或 Service的 stopSelf 来停止服务。

    在使用Service中有一个误区会有人以为在Service中的onCreate中能够进行耗时操作。这是不正确的,Service依旧是运行在主线程中的,假设直接进行耗时操作很easy造成ANR,所以即使在Service中耗时操作依旧要放到子线程其中。

    最后总结下什么情况下使用startService或bindService呢。假设你仅仅想启动一个后台服务去运行一个某项长期任务的话使用startService就能够了。假设你想要与正在运行的后台Service取得联系的话能够使用bindService,假设想要Service长期运行不随Activity销毁而且能够进行通信那么就调用了startService后再调用bindService。Service的总结先告一段落。有什么问题能够在下方留言,感谢。

    本篇源代码下载地址 http://download.csdn.net/detail/leejizhou/9459862

  • 相关阅读:
    javascript与CSS复习(《精通javascript》)
    javascript改进表单
    javascript与CSS复习(三)
    javascript dom代码应用:简单的相册
    重新发明轮子之Draggable Elements
    《精通javascript》5,6章复习(三)
    我的JAVA之旅(五)继承
    全面学习DBMS包之UTL_FILE
    想法
    生活在上海
  • 原文地址:https://www.cnblogs.com/clnchanpin/p/7223605.html
Copyright © 2011-2022 走看看