ANR源码分析之Service Timeout

本文详细分析了Service Timeout的流程,指出由于Service默认在UI线程运行,所以不能执行耗时操作以避免ANR。流程从startService开始,通过ContextImpl.java的realStartServiceLocked,再到ActivityThread的scheduleCreateService,服务超时时间默认为20s,后台线程则为200s。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 在前面的一篇文章中,分析了Broadcast Timeout的流程,接下来继续分析Service Timeout的流程。Service默认不会运行在子线程中,它也不会运行在一个独立的进程中,它同样执行在UI线程中,因此也不能在Service中执行耗时操作,否则也会产生的ANR。

 Service Timeout整体流程如下图所示:



1.startService(ContextImpl.java)

/*
    * 启动服务
    */
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, mUser);
    }


    private ComponentName startServiceCommon(Intent service, UserHandle user) {
        try {
            validateServiceIntent(service);//验证Service的Intent
            service.prepareToLeaveProcess(this);
            ComponentName cn = ActivityManagerNative.getDefault().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), getOpPackageName(), user.getIdentifier());//调用AMS的start方法


            ........
            return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
 2.startService(ActivityManagerService.java)
 在ActivityManagerService.java类中
 public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, String callingPackage, int userId)
            throws TransactionTooLargeException {
        enforceNotIsolatedCaller("startService");
        ......
        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid, callingPackage, userId);//调用ActiveServices的startServiceLocked方法
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }
3.startServiceLocked(ActiveServices.java)
    在ActiveServices.java类中
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, String callingPackage, final int userId)
            throws TransactionTooLargeException {


        final boolean callerFg;
        if (caller != null) {
         final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
         .........
         //调用者不是处于后台线程组中
         callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
       } else {
          callerFg = true;
        }
     .......
        S
ANR(Application Not Responding)错误是指应用程序在主线程上执行了太多的工作,导致界面无法响应用户的事件,从而出现了“应用程序无响应”的错误提示。在这种情况下,如果您的应用程序正在执行服务,那么该错误可能是由于服务执行超时导致的。 以下是解决这个问题的一些方法: 1. 使用IntentService: IntentService 是一种专门用于执行异步任务的服务。它可以在后台执行任务,并在完成任务后自动停止。使用 IntentService 可以避免在主线程上执行任务,从而避免 ANR 错误。 2. 使用线程池:如果您的应用程序需要在服务中执行大量的异步任务,可以使用线程池来管理这些任务。线程池可以在后台执行任务,并控制任务的数量和执行顺序,从而避免在主线程上执行过多的工作。 3. 使用HandlerThread:HandlerThread 是一种特殊的线程,它可以接收消息并在消息队列中处理这些消息。使用 HandlerThread 可以在后台执行任务,并避免在主线程上执行过多的工作。 4. 使用JobScheduler:JobScheduler 是一种 Android 系统提供的调度服务,它可以在特定的时间间隔或特定的条件下执行任务。使用 JobScheduler 可以避免在主线程上执行任务,并在系统空闲时执行任务,从而避免 ANR 错误。 请注意,如果您的应用程序需要执行长时间运行的任务,最好将这些任务移到后台线程中执行,以避免 ANR 错误。同时,还应该尽可能地优化代码,避免在主线程上执行过多的工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值