日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

      歡迎訪問 生活随笔!

      生活随笔

      當前位置: 首頁 > 运维知识 > Android >内容正文

      Android

      android service框架,Android应用框架之Service

      發布時間:2025/3/20 Android 45 豆豆
      生活随笔 收集整理的這篇文章主要介紹了 android service框架,Android应用框架之Service 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

      之前的博客已經介紹了應用框架中的Activity和Application,今天來講四大組件之一的Service。對于Service大家肯定都比較熟悉,與Activity最大的不同就是Service不會與界面打交道,而是始終工作在后臺,執行一些與UI無關的操作和計算。即便用戶切換了其他應用,啟動的Service仍可在后臺運行。一個組件可以與Service綁定并與之交互,甚至是跨進程通信(IPC)。

      Service運行在主線程中(A service runs in the main thread of its hosting process),Service并不是一個新的線程,也不是新的進程。也就是說,若您需要在Service中執行較為耗時的操作(如播放音樂、執行網絡請求等),需要在Service中創建一個新的線程。這可以防止ANR的發生,同時主線程可以執行正常的UI操作。

      Service有兩種啟動方式,一個是startService,一個是bindService,接下來分別介紹一下兩種方式的啟動邏輯。

      1.startService

      通常情況下啟動一個Service的代碼如下:

      Intent intent = new Intent(this, MyService.class);

      context.startService(intent);

      啟動過程是從Context開始的,而這個Context實際是一個ContextWrapper,而從ContextWrapper的實現看來,其內部實現都是通過ContextImpl來完成的,這是一種典型的橋接模式。通過調用ContextImpl的startService,會啟動一個服務,核心代碼如下所示:

      private Component startServiceCommon(Intent service, UserHandle user) {

      ......

      Component cn = ActivityManagerNative.getDefault().startService(mMainThread.getApplicationThread(),service,service.resolveTypeIfNeeded(getContentResolver()),user.getIdentifier());

      ......

      ContextImpl通過ActivityManagerNative.getDefault()獲取到一個服務,這個服務就是熟悉的Activity Manager Service(AMS),啟動這個服務的方式當然還是Binder機制。所起啟動Service的工作就轉移到了AMS身上。在AMS的內部還有一個mServices,這個對象是輔助AMS進行service管理的類,包括Service的啟動、綁定和停止等等。同時一個Service在AMS內部對應一個ServiceRecord,AMS用它來記錄各個Service。

      而在AMS內部會通過realStartServiceLocked方法來啟動Service,其實在AMS內部的啟動步驟還有還經過了很多方法,不過最為核心的就是realStartServiceLocked,該方法的核心代碼如下:

      private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException {

      ...... app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);

      app.thread.scheduleCreateService(r, r.serviceInfo, mMm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState);

      r.postNotification();

      ......

      }

      這里的app是一個ProcessRecord對象,就是在之前的博客中提到的AMS中用于記錄一個Application的對象。通過app.thread.scheduleCreateService方法來創建Service并調用其onCreate方法,接著在通過sendServiceArgsLocked方法來調用Service的其他方法,比如onStartCommand。而這兩個過程均是進程間通信,app.thread其實是一個IApplicationThread類型,實際就是一個Binder。而scheduleCreateService就是這個binder中的一個接口方法,接下來看一下對應的scheduleCreateService方法:

      public final void scheduleCreateService(Binder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) {

      updateProcessState(procesState, false);

      CreateServiceData s = new CreateServiceData();

      s.token = token;

      s.info = info;

      s.compatInfo = compatInfo;

      sendMessage(H.CREATE_SERVICE, s);

      }

      從代碼中可以看到,最后的創建工作又通過發送消息給Handler H將創建Service的工作又回到了ActivityThread中。最后再來看看ActivityThread的handleCreateService

      private void handleCreateService(CreateServiceData data){

      ......

      Service service = null;

      java.lang.ClassLoader cl = packageInfo.getClassLoader();

      service = (Service)cl.loadClass(data.info.name).newInstance();

      ......

      ContextImpl context = ContextImpl.createAppContext(this, packageInfo);

      context.setOuterContext(service);

      Application app = packageInfo.makeApplication(false, mInstrumentation);

      service.attach(context, this, data.info.name, data.token, app, ActivityManagerNative.getDefault());

      service.onCreate();

      mServices.put(data.token, service);

      ......

      }

      這個方法主要做了以下幾件事:

      1.通過創建類加載器,創建Service實例

      2.創建Application對象,并調用其onCreate方法,當然Application對象只會被創建一次

      3.創建ContextImpl對象,并通過service的onAttach方法建立兩者之間的聯系。這個過程和Activity類似,畢竟Activity和Service都是一個Context

      4.最后調用Service的onCreate方法,并將Service保存在ActivityThread中的一個列表mServices。

      由于Service的onCreate方法被執行了,接下來AcitivtyThread還會通過handleServiceArgs方法調用Service的onStartCommand方法:

      private void handleServiceArgs(ServiceData data) {

      Service s = mServices.get(data.token);

      ......

      if(!data.taskRemoved) {

      res = s.onStartCommand(data.args, data.flags, data.startId);

      } else {

      s.onTaskRemoved(data.args);

      res = Service.START_TASK_REMOVED_COMPLETE;

      }

      ......

      ActivityManagerNative.getDefault().serviceDoneExecuting(data.token, 1, data.startId, res);

      ......

      }

      在這個方法中可以看到,在service執行完成之后,還會通過ActivityManagerNative.getDefault().serviceDoneExecuting來通知AMS service已經執行完畢。

      最后來總結一下Service啟動的主要步驟:

      Context-->AMS-->app.thread-->ActivityThread-->Service

      為什么要去繞這么一大圈呢?其實很好理解,AMS管理各個組件,要創建一個新的service當然要通過AMS來維護一個與該service對應的實例并與對應的進程實現關聯,app.thread只是一個應用通信的接口,并將對應的工作交接給ActivityThread,ActivityThread才是應用的真正實例,它當然也要管理該Service,并維護一個對應的記錄(mServices)。其實Activity和Service的啟動過程大致相同,從中可以更加了解Android的應用框架。

      2.bindService

      bindService的大致過程過程和startService類似,還是通過contextImpl.bindServiceCommon來啟動:

      private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, UserHandle user) {

      IServiceConnction sd;

      ......

      sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), mMainThread.getHandler(), flags);

      ......

      int res = ActivityManagerNative.getDefault().bindService(mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, user.getIdentifier());

      ......

      }

      這里主要做了兩件事:

      將客戶端的ServiceConnection轉化為ServiceDispatcher.InnerConnection。之所以不能直接使用ServiceConnection是因為綁定的服務可能是跨進程的,所以必須借助于Binder才能讓遠程服務回調自己的方法。而ServiceDispatcher的內部類InnerConnction正好充當了這個Binder。所以ServiceDispatcher的作用就是ServiceConnection和InnerConnection連接的橋梁。

      調用AMS的bindService方法來完成Service的具體綁定過程。

      接下來重點講一下AMS的bindService方法。和startService方法類似的是,bindService最終會將調用到app.thread.scheduleBindService():

      public final void scheduleBindService(Binder token, Intent intent, boolean rebind, int processState) {

      updateProcessState(processState, false);

      BindServiceData s = new BindServiceData();

      s.token = token;

      s.intent = intent;

      s.rebind = rebind;

      ......

      sendMessage(H.BIND_SERVICE, s);

      }

      接下來又轉移到了ActivityThread中,而這個方法就是ActivityThread.handleBindService():

      private void handleBindService(BindServiceData data) {

      Service s = mServices.get(data.token);

      ......

      IBiner binder = s.onBind(data.intent); ActivityManagerNative.getDefault().publishService(data.token, data.intent, binder);

      ......

      }

      在handleBindService中,首先根據Service的token取出Service對象,然后調用Service的onBind方法。但是onBind方法是Service的方法,這個時候客戶端并不知道已經綁定成功了,所以還必須調用客戶端的ServiceConnection中的onServiceConnected,這個是由ActivityManagerNative.getDefault().publishService方法來完成的。最終指令流會轉移到mServices(AMS內部的輔助Service)的publishServiceLocked。其核心代碼只有一行:c.conn.connected(r.name, service),其中c.conn類型是ServiceDispatcher.InnerConnection,service就是Service的onBind返回的Binder對象。接下來看看ServiceDispatcher.InnerConnection的定義:

      private static class InnerConnection extends IServiceConnection.Stub {

      ...

      private void connected(ComponentName name, Binder service) throws RemoteException {

      LoadedApk.ServiceDispatcher sd = mDispacher.get();

      if(sd != null) {

      sd.connectd(name, service);

      }

      }

      }

      InnerConnection最后通過ServiceDispatcher的connected方法來調用ServiceConnection的onServiceConnected,至此綁定完成。

      總結

      以上是生活随笔為你收集整理的android service框架,Android应用框架之Service的全部內容,希望文章能夠幫你解決所遇到的問題。

      如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。