(二)Service

什么是Service
Service是一个长期运行在后台没有用户界面的Android组件。

在Android中后台是相对UI前台而言的,后台不是子线程。
ServiceThread没有任何关系
Service是运行在主线程中的,若直接在Service里面做耗时操作很容易造成ANR「Application Not Responding」,故在Service中不能直接做耗时操作,要想做耗时操作只能在Service中创建的子线程中进行。

  • Android中有两种Service
    1. Service
//AndroidManifest文件中注册service
 <service android:name=".test.MyService" />
  1.1 Service 是单向的  不受控的
@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent intent = new Intent(MainActivity.this, MyService.class);
        //启动Service
        startService(intent);
    }
//这个Service 是单向的  不受控的
// Context.startService(...)之后,Service的 onCreate()和onStartCommand(...)会得到执行。
//之后Service会一直处于运行状态,但具体运行的是什么逻辑,Context就控制不了了。
// 这就好比Activity通知了服务一下:『喂,哥们你可以干活去了』,然后服务就去忙自己的事情了,
// 但Activity并不知道Service到底去做什么了,以及完成的如何。
// Service去干活怎么干不受Context控制,
// Service与Context没任何交流
public class MyService extends Service {
   @Override
   public IBinder onBind(Intent intent) {
       return null;
   }
//会在Service第一次创建时调用
// 若多次调用Context.startService(...)  此方法只会执行一次
   @Override
   public void onCreate() {
       super.onCreate();
   }
//每次启动Service时调用
   @Override
   public int onStartCommand(Intent intent, int flags, int startId) {
       //new MyAsyncTask().execute();
       //创建并开启子线程进行耗时任务
       new Thread(new Runnable() {
           @Override
           public void run() {
               //耗时操作。。。
               Log.i("创建并开启子线程进行耗时任务", "run");
               //耗时操作处理完毕后  不一定要停掉Service 否则会造成内存泄漏
               stopSelf();
           }
       }).start();
       return super.onStartCommand(intent, flags, startId);
   }
//会在Service销毁时调用
   @Override
   public void onDestroy() {
       super.onDestroy();
   }
}
public class MyAsyncTask extends AsyncTask<Void, Integer, Boolean> {

    //在后台任务开始执行之前调用,用于进行一些界面上的初始化操作。(初始化工作)
    @Override
    protected void onPreExecute() {
        //显示进度对话框。。。
        super.onPreExecute();
    }

    /**
     * 这个方法中的代码都会在子线程中运行,在这里处理所有的耗时操作任务。
     * 这个方法中不可进行UI操作,可调用publishProgress(Progress...)来完成UI更新。
     * retun 返回任务的执行结果
     */
    @Override
    protected Boolean doInBackground(Void... voids) {
        //耗时操作
        return true;
    }

    /**
     * 调用publishProgress(...)方法后,onProgressUpdate这个方法就被调用,在这个方法中可以对UI进行操作
     */
    @Override
    protected void onProgressUpdate(Integer... values) {
        //更新UI   如进度条。。。
        super.onProgressUpdate(values);
    }

    /**
     * 当后台线程任务执行完毕并通过return进行返回时,
     * 这个方法就会被调用。在这个方法中根据传参(任务执行的结果)
     * 进行相应的UI及逻辑操作。
     */
    @Override
    protected void onPostExecute(Boolean aBoolean) {
        //关闭进度对话框  。。。
//此处 停止service
        super.onPostExecute(aBoolean);
    }
}
1.2  Service 是双向的  可控的
public class MyService2 extends Service {
    private static final String TAG = "MyService2";
    //Context通过Binder对Service进行控制
    private DownloadBinder downloadBinder = new DownloadBinder();

    @Override
    public IBinder onBind(Intent intent) {
        return downloadBinder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    class DownloadBinder extends Binder {
        public void startDownload() {
            Log.i(TAG, "startDownload...");
        }

        public int getProgress() {
            Log.i(TAG, "getProgress...");
            return 0;

        }
    }
}

//MainActivity中
  private MyService2.DownloadBinder downloadBinder;
    private ServiceConnection serviceConnection;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                downloadBinder = (MyService2.DownloadBinder) service;
                downloadBinder.startDownload();
                downloadBinder.getProgress();
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                downloadBinder.stopDownload();
            }
        };
        Intent intent = new Intent(MainActivity.this, MyService2.class);
        //绑定Service   BIND_AUTO_CREATE ---> 绑定之后自动创建Service
        bindService(intent, serviceConnection, BIND_AUTO_CREATE);
        
        //解绑
        unbindService(serviceConnection);
    }

注意: 若同时调用了bindService(intent, serviceConnection, BIND_AUTO_CREATE)和startService(intent),相应就要同时stopService(intent)和unbindService(serviceConnection)

  1. IntentService(增强版的Service,集开启线程,以及任务完成后停止service于一身)
//用法和普通的Service一样   startService(...) 或 bindService(...)
public class MyIntentService extends IntentService {
    public MyIntentService() {
        super("MyIntentService");
    }

    //这个方法已经在子线程,无需担心ANR
    //Serive任务完成后会自动停止服务
    @Override
    protected void onHandleIntent(Intent intent) {
        //耗时操作
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }


    @Override
    public IBinder onBind(Intent intent) {
        return super.onBind(intent);
    }
}

使用场景

  1. 前台保活

    • 使用服务的原因:普通服务(后台服务)的优先级低,系统出现内存不足时,很容易回收掉正在后台运行的服务。「比如后台运行播放音乐,用着用着音乐服务没了」。若想让服务一直保持运行状态,而不会由于系统内存不中的原因导致被回收,就可以考虑使用前台服务。
  2. 普通服务与前台服务的区别

    • 一直有一个正在运行的图标在系统的状态栏显示,下拉状态栏可以看到更加详细的信息,类似于通知的效果。
//只需要修改一下MyService类中的onCreate方法
@Override
  public void onCreate() {
      super.onCreate();
      Intent intent = new Intent(this, MainActivity.class);
      PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
      Notification notification = new NotificationCompat.Builder(this)
              .setContentTitle("this is content title")
              .setContentText("this is content text")
              .setWhen(System.currentTimeMillis())
              .setSmallIcon(R.mipmap.ic_launcher)
              .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
              .setContentIntent(pi)
              .build();
      startForeground(1, notification);

  }

原理

参考:
https://developer.android.google.cn/guide/components/services#Foreground

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

推荐阅读更多精彩内容

  • Service也是一个单独的Android组件。通常用于为其他组件提供后台服务或者监控其他组件的运行状态。 Act...
    Rave_Tian阅读 1,022评论 0 0
  • 只是写一遍加深印象。 1 概述 一种后台服务。使用时需要在Manifest声明。两种使用方式: 启动模式。适用于S...
    落水木木阅读 377评论 0 0
  • 一段时间不用,知识点就会忘,所以整理下一些基本的知识点,加深下印象,便于以后复习。这篇说一下Android中四大组...
    朋永阅读 463评论 0 2
  • 2.1 Activity 2.1.1 Activity的生命周期全面分析 典型情况下的生命周期:在用户参与的情况下...
    AndroidMaster阅读 3,040评论 0 8
  • 原创日记(251)2017.11.01 多云 日记记录我生活的婆婆妈妈。 幸福生活黑茶永相伴! 今天尝试了一种特别...
    黑金公主阅读 143评论 0 0