关于Service你一定要知道的

       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,并会将通知的图片显示出来。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容