AndroidAZ系列: 四大组件之Service(All,Face)

四大组件之Service

Git仓库地址

配套四维导图地址

AndroidAZ系列有以下目的:

  1. Android程序猿的面试(初级,中级,高级,资深),拿到满意的offer。
  2. Android程序猿学习进阶。

标记说明:因为笔者是列出所有的Android知识点,因此面试不需要看那么多内容,如果是面试的知识点。笔者会加上标记Face,而如果不是面试的知识点,笔者会加上No标记,它是要学的东西;然后笔者将Android面试者或者面试者分为4个等级,初级A1,中级A2,高级A3,资深A4,如果这个知识点是所有等级的范围,那么笔者将会以all标记上。因此进阶路线就是A1->A2->A3->A4。也是面试者挑选的复习范围,假如你是中级程序员,那么你面试要看的内容就是包含A2&Face的标记。

  • All : 所有的Android工程师都看。

  • A1: 初级Android工程师。

  • A2: 中级Android工程师。

  • A3: 高级Android工程师。

  • A4: 资深Android工程师。

  • Face: 是面试的知识点。

  • No: 面试基本遇不到。

1.Service 是什么

Android Service是Android四大组件之一,它主要用来执行一些不与用户交互的长期运行的任务. 服务的运行不依赖于任何用户界面,即使程序被切换到后台,或者用户打开了另一个应用程序,服务仍然能够保持正常运行. 另外Service并不是运行在单独线程中,而是主线程中。所以尽量要避免耗时操作。

2.Service和线程的区别

2.1 线程的用法

  • 方法一:

    class MyThread extends Thread{
        @Override
        public void run(){
            // 耗时操作
        }
    }
    new MyThread().start();
    
  • 方法二:

    class Mythread implements Runnable{
        @Override
        public void run(){
            // 耗时操作
        }
    }
    Mythread mythread = new Mythread();
    new Thead(mythread).start();
    

2.2 在子线程中更新UI

  • 方法一:

    public static final int MSG_ID = 100;
    private Handler handler = new Handler(){
        public void handleMessage(Message msg){
            switch(msg.what){
                case MSG_ID:
                    // 更新UI
                    break;
                default:
                    break;
            }
        }
    }
    
    new Thread(new Runnable(){
        @Override
        public void run(){
            Message message = new Message();
            message.what = MSG_ID;
            handler.sendMessage(message);
        }
    }).start();
    
  • 方法二:

    这里的原理和方法一是一样的,只是进行了封装

    @android.webkit.JavascriptInterface
        public void actionFromJs() {
            mMainView.getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    MusicPlayerHelper.getIntence(mMainView.getContext().getApplicationContext()).stopBgSound();
                    Intent intent = new Intent();
                    intent.setClass(mMainView.getContext(), NocviceActivity.class);//打开一个activity
                    mMainView.getActivity().startActivity(intent);
                }
            });
        }
    

2.3 服务的用法

  1. 定义一个服务
public class MyService extends Service{
    public MyService(){
    }

    @Override
    public IBinder onBind(Intent intent){
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @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();
    }
}
  1. 在AndroidManifest.xml中进行注册
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:lable="@string/app_name"
    android:suppertsRtl="true"
    android:theme="@style/AppTheme">
    ...
    <service
        android:name=".MyService"
        android:enable="true"
        android:exported="true">
    </service>
</application>
  1. 启动服务
Intent startIntent = new Intent(mContext,MyService.class);
mContext.startService(startIntent);
  1. 停止服务
Intent stopIntent = new Intent(mContext,MyService.class);
mContext.stopService(startIntent);

Service和Thread的区别

  • Service

    1. 在后台用来执行长时间运行操作的应用组件

    2. Service的生命周期在主线程中执行,如果要执行耗时操作,需要开启一个分线程

    3. 应用退出,Service也不会停止

    4. 再次启动应用时,还可以和正在运行的Service通信

  • Thread

    1. 用来开启一个分线程的类,用来做耗时操作

    2. Thread类的run()在分线程执行

    3. 应用退出,Thread也不会停止

    4. 再次启动应用,不能再控制之前的Thread对象

  • 详细解释

    其实这跟 android 的系统机制有关,我们先拿Thread 来说。Thread 的运行是独立于 Activity 的,也就是说当一个 Activity 被 finish 之后,如果你没有主动停止 Thread 或者 Thread 里的 run 方法没有执行完毕的话,Thread 也会一直执行。因此这里会出现一个问题:当 Activity 被 finish 之后,你不再持有该 Thread 的引用。另一方面,你没有办法在不同的 Activity 中对同一 Thread 进行控制

    如果你的 Thread 需要不停地隔一段时间就要连接服务器做某种同步的话,该 Thread 需要在 Activity 没有start的时候也在运行。这个时候当你 start 一个 Activity 就没有办法在该 Activity 里面控制之前创建的 Thread。因此你便需要创建并启动一个 Service ,在 Service 里面创建、运行并控制该 Thread,这样便解决了该问题(因为任何 Activity 都可以控制同一 Service,而系统也只会创建一个对应 Service 的实例)

    因此你可以把 Service 想象成一种消息服务,而你可以在任何有 Context 的地方调用Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也可以在 Service 里注册 BroadcastReceiver,在其他地方通过发送 broadcast 来控制它,当然这些都是 Thread 做不到的

3.Service的生命周期

Service生命周期图

3.1 startService

  1. 启动Service服务

    单次:startService() —> onCreate() —> onStartCommand()

    多次:startService() —> onCreate() —> onStartCommand() —> onStartCommand()

  2. 停止Service服务

    stopService() —> onDestroy()

3.2 bindService

  1. 绑定Service服务

    bindService() —> onCreate() —> onBind()

  2. 解绑Service服务

    unbindService() —> onUnbind() —> onDestroy()

  3. 启动绑定Service服务

    startService() —> onCreate() —> onStartCommand() —> bindService() —> onBind()

  4. 解绑停止Service服务

    unbindService() —> onUnbind() —> stopService() —> onDestroy()

  5. 解绑绑定Service服务

    unbindService() —> onUnbind(ture) —> bindService() —> onRebind()

3.3 onStartCommand()和onStart()区别

每调用一次startService()方法, onStartCommand()就会执行一次

onstart()方法是在android2.0一下的版本中使用。而在android2.0以上则使用onstartCommand()方法。它们两个方法放在一起使用时,不会产生冲突

4.Intent Service的使用

Intent Service时一个异步的 会自动停止的服务

public class MyIntentService extends IntentService{
    public MyIntentService(){
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent){
        // 耗时操作
        Log.d("MyIntentService","This is is" + Thread.currentThread().getId());
    }

    @Override
    public void onDestroy(){
        super.onDestroy();
        Log.d("MyIntentService","onDestroy executed");
    }
}

这里首先要提供一个无参的构造函数,并且必须在其内部调用父类的构造函数.然后要在子类中去实现onHandleIntent()这个抽象方法,在这个方法里执行耗时逻辑,而不用担心ANR的问题,因为这个方法已经是在子线程中运行了.

5. Service使用场景

Service是一个应用程序中不可见的组件,用于处理运行时间长或者不需要用户交互的任务,比如一个股票应用,应用程序关掉了但是要给用户实时提供最新的数据,这时就可以使用Service

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