-ANR causas e soluções Android otimização de desempenho

1, a emergência da situação ANR

Satisfaz o seguinte caso o sistema solicitará a ANR pop

eventos de entrada (chave e toque eventos) não foi processado dentro dos 5S;
(método onRecieve ()) eventos BroadcastReceiver dentro do tempo especificado não processados (broadcast primeiro plano para os 10s, transmissão bastidores para os anos 60);
Serviço de primeiro plano 20s 200s fundo não completou a inicialização ;
o ContentProvider a publicar () não ser concluída dentro de 10s.
Em circunstâncias normais que causou o thread principal está bloqueada.

2. O princípio da ANR

Nenhuma resposta a uma entrada de um processo de exemplo (com base no código 9.0):

ANR pop-up posição da caixa de diálogo e de classe handleShowAnrUi finais AppErrors de método AMS mesmo diretório (). Essa classe é usada para lidar com uma variedade de erro ocorreu no programa, não só a ANR, esta classe também forçou processo Bater.

 

    // base/core/java/com/android/server/am/AppErrors.java
    void handleShowAnrUi(Message msg) {
        Dialog dialogToShow = null;
        synchronized (mService) {
            AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
            // ...

            Intent intent = new Intent("android.intent.action.ANR");
            if (!mService.mProcessesReady) {
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                        | Intent.FLAG_RECEIVER_FOREGROUND);
            }
            mService.broadcastIntentLocked(null, null, intent,
                    null, null, 0, null, null, null, AppOpsManager.OP_NONE,
                    null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);

            boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
                    Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
            if (mService.canShowErrorDialogs() || showBackground) {
                dialogToShow = new AppNotRespondingDialog(mService, mContext, data);
                proc.anrDialog = dialogToShow;
            } else {
                MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
                        AppNotRespondingDialog.CANT_SHOW);
                // Just kill the app if there is no dialog to be shown.
                mService.killAppAtUsersRequest(proc, null);
            }
        }
        // If we've created a crash dialog, show it without the lock held
        if (dialogToShow != null) {
            dialogToShow.show();
        }
    }

No entanto, chamadas a partir do local de ocorrência para ANR aqui para passar por um monte de classes e métodos. ANR é inicialmente jogado na InputDispatcher.cpp no. Nós podemos definir constantes para encontrar o local onde o gatilho inicial:

 

// native/services/inputflinger/InputDispatcher.cpp
constexpr nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec

A partir da posição desta classe será acionado atravessou camadas de InputManagerService alcance

 

// base/services/core/java/com/android/server/input/InputManagerService.java
private long notifyANR(InputApplicationHandle inputApplicationHandle,
        InputWindowHandle inputWindowHandle, String reason) {
    return mWindowManagerCallbacks.notifyANR(
            inputApplicationHandle, inputWindowHandle, reason);
}

mWindowManagerCallbacks aqui é InputMonitor:

 

// base/services/core/java/com/android/server/wm/InputMonitor.java
public long notifyANR(InputApplicationHandle inputApplicationHandle,
        InputWindowHandle inputWindowHandle, String reason) {
    // ... 略

    if (appWindowToken != null && appWindowToken.appToken != null) {
        final AppWindowContainerController controller = appWindowToken.getController();
        final boolean abort = controller != null
                && controller.keyDispatchingTimedOut(reason,
                        (windowState != null) ? windowState.mSession.mPid : -1);
        if (!abort) {
            return appWindowToken.mInputDispatchingTimeoutNanos;
        }
    } else if (windowState != null) {
        try {
            // 使用 AMS 的方法
            long timeout = ActivityManager.getService().inputDispatchingTimedOut(
                    windowState.mSession.mPid, aboveSystem, reason);
            if (timeout >= 0) {
                return timeout * 1000000L; // nanoseconds
            }
        } catch (RemoteException ex) {
        }
    }
    return 0; // abort dispatching
}

No método acima é chamado e, em seguida, volta para o AMS inputDispatchingTimedOut () método continua a processo e, eventualmente, inputDispatchingTimedOut () método será passado para os AppErrors evento

 

// base/services/core/java/com/android/server/am/ActivityManagerService.java
public boolean inputDispatchingTimedOut(final ProcessRecord proc,
        final ActivityRecord activity, final ActivityRecord parent,
        final boolean aboveSystem, String reason) {
    // ...

    if (proc != null) {
        synchronized (this) {
            if (proc.debugging) {
                return false;
            }

            if (proc.instr != null) {
                Bundle info = new Bundle();
                info.putString("shortMsg", "keyDispatchingTimedOut");
                info.putString("longMsg", annotation);
                finishInstrumentationLocked(proc, Activity.RESULT_CANCELED, info);
                return true;
            }
        }
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                // 使用 AppErrors 继续处理
                mAppErrors.appNotResponding(proc, activity, parent, aboveSystem, annotation);
            }
        });
    }

    return true;
}

Quando os eventos são passados ​​para os AppErrors, ele vai ajudar Handler vai processar a mensagem chama o método original e caixa de diálogo pop-up.

Referência: "princípio ANR Android de análise"

3, solução ANR

Análise das causas e princípios da ANR acima, vamos analisar a forma de resolver o ANR.

1. Use adb log de exportação ANR e analisar

ANR sistema ocorre quando a gravação de informação e arquivo ANR /data/anr/traces.txt armazenada no (relativamente novo no sistema é armazenado em ambos / data / ANR / anr_ arquivo *). Nós podemos usar as seguintes maneiras de exportá-lo para o seu computador, a fim de ANR razão gerado para análise:

 

adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>

Quando a análise I ANR ao usar o try comando ANR aos registros de exportação surgiram Permissão negada. Após este tempo, você pode exportar o telefone depois Root, ou tentar modificar as permissões para ler e escrever arquivos, ou optar por exportar os logs para o sdcard no modo de desenvolvedor sdcard e, em seguida, enviar os logs para o terminal de computador para visualização

análise DDMS 2. Use traceview

DDMS abrir no AS, ou para usar o diretório de instalação do SDK diretório monitor.bat abertas DDMs ferramentas abaixo.

Use as ferramentas TraceView pode consultar o artigo: "análise de desempenho TraceView Android do uso (aplicação de análise demorada)"

Esta ideia posicionamento ANR é: use as informações de localização para localizar TraceView método demorado chamada operação demorada.

informações:

3. Use projeto de código aberto ANR-WatchDog detecta ANR

endereço projeto é  Github-ANR-WatchDog

O princípio do projeto: criar uma linha de detecção que continuam a segmento interface do usuário postar uma tarefa, e depois dormir um tempo fixo, como antes e novamente após o segmento a tarefa de detectar se ou não para executar o cargo, assumindo que a tarefa não está em execução, geração ANRError, e terminar o processo.

cena 4. ANR Comum

I / O bloqueio de
congestionamento da rede
multithreading impasse
devido aos resultados do método em um ciclo de programação reativa a morrer
devido a um tempo de execução lógica de negócios é muito longo

5. O método de evitar ANR


segmento interface do usuário apenas na medida do possível, o trabalho associado com a interface do usuário;
; de trabalho (tais como as operações de banco de dados, I / O, operações de rede, etc.), utilizando um processamento segmento de trabalho separada demorado
com Handler para segurar a linha UI interativo e os segmentos de trabalho;
uso RxJava e outras mensagens assíncronas para processar.
Em suma, um princípio é: não no thread principal para fazer a operação demorada.

Publicado 56 artigos originais · ganhou elogios 1 · vista 2913

Acho que você gosta

Origin blog.csdn.net/chuhe1989/article/details/104564521
Recomendado
Clasificación