zoukankan      html  css  js  c++  java
  • Android Service 文档

    应用场景:

        1  用于将后台逻辑(Service中)和UI逻辑(Activity中)进行解耦,实现Service功能的复用,为其他程序提供功能。

        2  后台功能,由于Activity在进入后台时(OnStop)不会占用CPU进行运算,而Service在后台会一直占用CPU,用Service可以达到多任务效果。

        3  默认情况下,Service运行在主线程(UI线程)中,因此耗时的操作(下载)需要在Service新建线程处理或者使用异步(AsyncTask)的方式进行。

        4  桌面widget的功能需要用Service实现。

        5  能提高进程优先级,当Android系统由于内存资源不足时会考虑将进程回收,此时若需要保证进程不会被结束,将Service运行在前台模式(foreground),此时该进程的优先级与前台进程一样。

        6  IntentService类,对于简单的后台任务可以用IntentService实现。

    相关回调函数以及生命周期

        7  onCreate与onDestroy,相当于构造函数和析构函数,整个生命周期都只执行一次。不论startService或者bindService调用多少次,进程中的同一个Service只会在第一次时执行onCreate;而onDestroy需要调用stopService(若有startService,多次startService只需要一次stopService)和unbindService(若有bindService,每个bindService都要有相应的unbindService)后才会执行。

        8  onBind,调用bindService时,若Service还没有启动,则根据不同的flags参数,会有不同的行为。

            1) 0,默认值,不启动Service,而当有其他情况使得Service启动时,会自动绑定该Serivce。

            2) BIND_AUTO_CREATE,若此时Service还没有启动,则直接启动Service。

            3) BIND_DEBUG_UNBIND,会将bindService的调用栈保留以备调试的时候使用。

            4) BIND_IMPORTANT,表明该Service非常重要,并且会将进程优先级设为前台进程级别。

            5) BIND_NOT_FOREGROUND,不允许Service所在进程成为前台进程。

            6) BIND_WAIVE_PRIORITY,不影响Service所在进程的调度和内存优先级。

    • onBind的主要作用是与调用者通过返回值IBinder建立连接,以便进行交互。

        9  onUnbind,调用unbindService时执行,其返回值影响onRebind回调的运行情况。只有当返回值为true,onRebind才能运行。

       10  onRebind,当Service由于内存不足被系统回收后,内存再次足够时,Service重新启动后就会执行。受onUnbind返回值影响。

       11  onStartCommand,每次调用startService都会执行该回调函数。如果有一次性的任务可以放在该函数中执行,这样每次调用startService都会执行该任务。

    后台服务最佳实践

       12  不要在Service中直接进行耗时操作,这样会阻塞主线程(UI),应该将其放到另外的线程中运行。

       13  对于简单可重复的任务,优先推荐使用IntentService。IntentService类中有自己的线程处理任务。通过在传递的Intent中附带数据,使用Broadcast将Service中信息传回客户端[1]进行通信。

       14  使用AlarmManager、Thread和Service实现轮询,能只用AlarmManager就尽量不要带Service[2]

       15  保持Service一直运行的方案:

            1) 提升优先级,设为foreground运行,

            2) 注册系统广播(开机启动、屏幕解锁等),

            3) 开启两个Service,相互绑定监听,若对方被强制结束就将其重启(微信、QQ等),

            4) 将程序安装到/system/app中,使其成为系统程序,需要root权限。

    Service客户端相关

    安卓Service组件的客户端就是能进行startService/stopService和bindService/unbindService操作的组件,一般情况下Activity、Broadcast receiver和Service都可以成为Service组件的客户端。

    Activity是最常用的Service客户。对于Activity可以在其onCreate()/onDestroy(), onStart()/onStop(), onPause()/onResume()中实现启动和绑定Service/停止和解绑定操作(如果需要Service在后台运行,那么就不需要停止操作),因为这三组Activity回调在其生命周期中都是一一对应的,也就对应了Service资源的分配和回收情况。其中onCreate()/onDestroy()对应了服务需要在整个app的生命周期中都持续进行的情况,比如IM软件需要在后台持续进行网络通信服务,如果在其他两组回调中实现,那么一旦app进入后台,网络连接就会断掉(一般IM软件不会在onDestroy中停止Service,而是保持Service运行以保证不会错过消息);onStart()/onStop()对应的是该Activity在前台时需要的服务,比如更新Activity的UI界面时,这种情况下一旦onStop就结束Service并进行资源回收(主要防止serviceConnectionLeak),当Activity重新可见时,就重新开启并绑定Service。并不推荐在onPause()/onResume()中进行Service绑定和解绑定,因为这两个回调的执行频率非常高,应该要保持这中间的代码尽量只做轻量级的工作。除了在Activity的生命周期回调中绑定和解绑定Service外,还可以由UI事件触发(比如Button的click事件),此时必须要注意是否已经绑定,以及后续解绑定(可以放在onDestroy或onStop中),防止serviceConnectionLeak。

    对于Broadcast receiver,其生命周中最主要就是onReceive回调,因此Service常常在此回调中开启。由于receiver的生命周期非常短(不能超过10s,否则就会ANR),因此不能使用bindService,只能startService开启服务。比如安卓的开机自启动就是通过接收BOOT_COMPLETED这个广播实现的,首先继承BroadcastReceiver类并在onReceive中开启Service,最后在AndroidManifest.xml 文件中注册该receiver。

    Service和Service相互服务一般就是为了监控对方的运行状态以防止被系统收回。另外Service还可以直接为UI组件进行服务,比如在Service生命周期更新Notification的状态等。

    Service绑定交互

    Service与客户端绑定后进行交互主要有三种方法:Binder、Messenger和AIDL。

    第一种方法适合与Service和客户运行在同一个进程中,比如Service由Activity启动并绑定的。在Service的onBind中返回Binder,客户Activity接收此Binder,并通过调用Binder公有方法甚至Service的方法与Service的交互。除非需要与其他进程的组件进行交互,就应该首选该方案。

    第二种方法是使用Messenger,在此方法中Service需要定义一个Handler以处理各种Message。客户端通过该Service返回的Binder中获取到Messenger,通过向该Messenger发送Message,Service中的Handler进行处理,客户端也可以定义自己的Messenger,这样Service可以将Message传回给客户端。通过这种方式可以实现进程间的通信,这也是安卓推荐的IPC方式。

    最后一种是使用AIDL(Android Interface Definition Language)。Messenger的底层实际上就是使用AIDL实现的。这种方法需要用aidl文件定义编程接口,然后由Android SDK 工具生成对应的接口类,最后实现这些接口。该方法与Messenger的优势是效率高,Messenger通过Handler进行消息处理,Handler使用消息队列,一次只能处理一个Message,AIDL则没有这种限制。缺点是服务器和客户端都需要aidl文件,它们之间的接口要保持兼容,因此IPC优先推荐使用Messenger。

    除了通过Bind到Service进行交互外,还可以使用Application组件在一个程序的各个组件之间进行数据分享。主要思路是将数据保存在Application中,Application实现为一个Observer,其他组件实现为Listener,注册到Application上,这样当数据发生变动时,通知所有的Listener调用相应的回调。

        

  • 相关阅读:
    2021,6,10 xjzx 模拟考试
    平衡树(二)——Treap
    AtCoder Beginner Contest 204 A-E简要题解
    POJ 2311 Cutting Game 题解
    Codeforces 990G GCD Counting 题解
    NOI2021 SDPTT D2T1 我已经完全理解了 DFS 序线段树 题解
    第三届山东省青少年创意编程与智能设计大赛总结
    Luogu P6042 「ACOI2020」学园祭 题解
    联合省选2021 游记
    Codeforces 1498E Two Houses 题解 —— 如何用结论吊打标算
  • 原文地址:https://www.cnblogs.com/wbin91/p/4494750.html
Copyright © 2011-2022 走看看