美文网首页
关于Service你一定要知道的

关于Service你一定要知道的

作者: Kyunban | 来源:发表于2017-08-27 03:20 被阅读0次

           Service是Android四大组件之一,主要用于执行需要长时间运行的任务或者处理一些耗时的逻辑。Service可以在程序退出后,在后台继续运行。

    一、Service的基本用法

    启动Service的方法和启动Activity很类似,都需要借助Intent来实现,构建出一个Intent对象,调用startService()方法来启动Service。然后同样构建出了一个Intent对象,并调用stopService()方法来停Service。当启动一个Service的时候,会调用该Service中的onCreate()和onStartCommand()方法。

    启动Service:

    Intent startIntent =newIntent(this,MyService.class);

    startService(startIntent);

    关闭service:

    Intent pauseIntent =newIntent(this,MyService.class);

    stopService(pauseIntent);

           onCreate()方法只会在Service第一次被创建的时候调用,如果当前Service已经被创建过了,不管怎样调用startService()方法,onCreate()方法都不会再执行,只会执行onStartCommand()方法。启动Service之后,就可以在onCreate()或onStartCommand()方法里去执行一些具体的逻辑了。

           项目中的每一个Service都必须在AndroidManifest.xml中注册。

    二、Service和Activity通信

          Service中有一个onBind()方法,这个方法就是用来和Activity通信的。通常会新增了一个类继承自Binder类,然后在这个类里写我们的逻辑,再通过onBind()方法将这个类的实例返回到activity中。因此service类应该是这样的:

    public class MyService extends Service {

    public static final String TAG ="MyService";

    private MyBinder mBinder =new MyBinder();

    @Override

    public void onCreate() {

    super.onCreate();

    Log.i(TAG,"onCreate() executed");

    }

    @Override

    public int onStartCommand(Intent intent,int flags,int startId) {

    Log.i(TAG,"onStartCommand() executed");

    return super.onStartCommand(intent, flags, startId);

    }

    @Override

    public void onDestroy() {

    super.onDestroy();

    Log.i(TAG,"onDestroy() executed");

    }

    @Override

    publicI Binder onBind(Intent intent) {

    return mBinder;

    }

    class MyBinder extends Binder {

    public void startDownload() {

    Log.i("TAG","startDownload() executed");

    }

    }

    }

    在activity里与service关联上,首先创建一个ServiceConnection的匿名类,在里面重写了onServiceConnected()方法和onServiceDisconnected()方法,这两个方法会在Activity与Service建立关联和解除关联的时候调用。在onServiceConnected()方法中,通过向下转型得到了MyBinder的实例,即我们在service里返回的Binder的子类的实例。在Activity中根据具体的场景来调用Binder的子类中的任何public方法,即Activitys可以指挥Service干什么Service就去干什么。代码:

    private ServiceConnection connection = new ServiceConnection() {

    @Override

    public void onServiceDisconnected(ComponentName name) {

    }

    @Override

    public void onServiceConnected(ComponentName name, IBinder service) {

    myBinder = (MyService.MyBinder) service;

    myBinder.startDownload();

    }

    };

    Activity和Service的关联由bindService()方法来完成。构建出一个Intent对象,然后调用bindService()方法将Activity和Service进行关联。bindService()方法接收三个参数,第一个参数是Intent对象,第二个参数ServiceConnection的实例,第三个参数是一个标志位,这里传入BIND_AUTO_CREATE表示在Activity和Service建立关联后自动创建Service,这会使得MyService中的onCreate()方法得到执行,但onStartCommand()方法不会执行。

    关联:

    Intent bindIntent =newIntent(this, MyService.class);

    bindService(bindIntent, connection, BIND_AUTO_CREATE);

    解除关联:

    unbindService(connection);

    注意,任何一个Service在整个应用程序范围内都是通用的,即MyService不仅可以和MainActivity建立关联,还可以和任何一个Activity建立关联,而且在建立关联时它们都可以获取到相同的MyBinder实例。

    三、销毁Service

    stopService()只会让Service停止,unbindService只会让Service和Activity解除关联,一个Service必须要在既没有和任何Activity关联又处理停止状态的时候才会被销毁。

    四、Service和Thread的关系

    Service和Thread之间没有任何关系!Thread是用来开启一个子线程,在Thread里执行一些耗时操作就不会阻塞主线程的运行。实际上,Service是运行在主线程里的。可以这样检验:

    在activity里打印当前线程编号:

    Log.i("MyService","MainActivity thread id is "+ Thread.currentThread().getId());

    在service里打印当前service的线程编号:

    Log.i("MyService","MyService thread id is "+ Thread.currentThread().getId());

    Android的后台就是指,它的运行是完全不依赖UI的。即使Activity被销毁,或者程序被关闭,只要进程还在,Service就可以继续运行。比如说一些应用程序,始终需要与服务器之间始终保持着心跳连接,就可以使用Service来实现。你可能又会问,前面不是刚刚验证过Service是运行在主线程里的么?在这里一直执行着心跳连接,难道就不会阻塞主线程的运行吗?当然会,但是我们可以在Service中再创建一个子线程,然后在这里去处理耗时逻辑就没问题了。
    一个比较标准的Service就可以写成:

    @Override

    public int onStartCommand(Intent intent, int flags, int startId) {

    new Thread(new Runnable() {

    @Override

    public void run() {

    // 开始执行后台任务

    }

    }).start();

    return super.onStartCommand(intent, flags, startId);

    }

    class MyBinder extends Binder {

    public void startDownload() {

    new Thread(new Runnable() {

    @Override

    public void run() {

    // 执行具体的下载任务

    }

    }).start();

    }

    }

    五、创建前台Service

    Service几乎都是在后台运行的。因为Service的系统优先级是比较低的,当系统出现内存不足时,就有可能会回收掉正在后台运行的Service。如果希望Service一直保持运行状态,而不会由于系统内存不足的原因导致被回收,可以考虑使用前台Service。前台Service和普通Service最大的区别就在于,它会一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏后可以看到更加详细的信息,非常类似于通知的效果。方法就是在service里设置一下:

    public class MyService extends Service {

    public static final String TAG = "MyService";

    private MyBinder mBinder = new MyBinder();

    @Override

    public void onCreate() {

    super.onCreate();

    // 在API11之后构建Notification的方式

    Notification.Builder builder = new Notification.Builder

    (this.getApplicationContext()); //获取一个Notification构造器

    Intent nfIntent = new Intent(this, MainActivity.class);

    builder.setContentIntent(PendingIntent.

    getActivity(this, 0, nfIntent, 0)) // 设置PendingIntent

    .setLargeIcon(BitmapFactory.decodeResource(this.getResources(),

    R.mipmap.ic_large)) // 设置下拉列表中的图标(大图标)

    .setContentTitle("下拉列表中的Title") // 设置下拉列表里的标题

    .setSmallIcon(R.mipmap.ic_launcher) // 设置状态栏内的小图标

    .setContentText("要显示的内容") // 设置上下文内容

    .setWhen(System.currentTimeMillis()); // 设置该通知发生的时间

    Notification notification = builder.build(); // 获取构建好的Notification

    notification.defaults = Notification.DEFAULT_SOUND; //设置为默认的声音

    startForeground(1, notification);

    Log.d(TAG, "onCreate() executed");

    }

    .........

    }

    首先在MyService的onCreate()方法中创建了一个Notification对象,然后调用了它的setLatestEventInfo()方法来为通知初始化布局和数据,并在这里设置了点击通知后就打开MainActivity。然后调用startForeground()方法就可以让MyService变成一个前台Service,并会将通知的图片显示出来。

    相关文章

      网友评论

          本文标题:关于Service你一定要知道的

          本文链接:https://www.haomeiwen.com/subject/khvydxtx.html