Capítulo Oito Otimização da Inicialização do Aplicativo de Otimização de Desempenho (2)

Capítulo Oito Otimização da Inicialização do Aplicativo de Otimização de Desempenho (2)

(1) Tela inicial tela branca / resolução da tela preta

1. Fenômeno

Quando você abre o aplicativo, geralmente faz uma pausa por um tempo antes de entrar na página de inicialização (Splash)

2. Razão

No método onCreate () de iniciar o Acitivty, o sistema desenha o formulário primeiro e, em seguida, executa o setContentView (R.layout.activity_splash) Após o desenho do formulário, os recursos do layout não são carregados, portanto a cor de fundo padrão é usada.
Se o tema usar Theme.AppCompat.Light (sistema de cores claras), ele exibirá uma tela de apresentação branca; se usar ThemeOverlay.AppCompat.Dark (sistema de cores escuras), exibirá uma tela de apresentação preta.

3. Resolver

Etapa 1: definir a imagem de inicialização bg_splash como plano de fundo do formulário, para evitar a aparência quando o aplicativo é iniciado, tela em preto / branco
Etapa 2: quando definida como a exibição de bg_splash em segundo plano, o plano de fundo é responsável por carregar os recursos e fazer o download da imagem de publicidade Mostrar a verdadeira aparência do SplashActivity quando o sucesso ou o tempo limite esgotar
Etapa 3: Em seguida, insira MainAcitivity

       <style name="ThemeSplash" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:background">@mipmap/bg_splash</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowFullscreen">true</item>
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        </style>

(2) Otimização da velocidade inicial

1. Análise do processo de inicialização do aplicativo Android

(1) Teoria básica do aplicativo

Cada aplicativo Android está em um espaço separado, o que significa que é executado em um processo separado, possui sua própria VM e recebe um ID de usuário exclusivo do sistema.O
aplicativo Android consiste em muitos componentes diferentes, que também podem iniciar outros Componentes do aplicativo. Portanto, o aplicativo Android não possui um método main () semelhante à entrada do programa. O
processo Android é o mesmo que o processo Linux. Por padrão, cada apk é executado em seu próprio processo Linux. Além disso, existe apenas um no processo padrão. Thread - o thread principal.Há uma instância Looper nesse thread principal, e a mensagem é recuperada da fila Message chamando Looper.loop () para o processamento correspondente. O
processo é iniciado quando necessário. A qualquer momento, quando o usuário ou outros componentes Quando você chama qualquer um dos componentes do seu apk, se o seu apk não estiver em execução, o sistema criará um novo processo para ele e o iniciará.Em geral, esse processo continuará sendo executado até que seja morto pelo sistema.

(2) processo de inicialização do aplicativo

Insira a descrição da imagem aqui
Quando o usuário clica no ícone de um aplicativo na Página inicial para iniciar um aplicativo: o
evento Click chamará startActivity (Intent), o Launcer usará o mecanismo IPC do Binder e notificará finalmente o ActivityManagerService (AMS é um processo do sistema Android, usado para gerenciar a operação dos quatro principais componentes do sistema Status) para iniciar a Atividade.
O Serviço executará as seguintes operações: A
primeira etapa: coletar as informações apontadoras deste objeto de intenção por meio de resolveIntent () do PackageManager. As informações apontadoras são armazenadas em um objeto de intenção. A
segunda etapa: verificar se o usuário possui o suficiente pelo método grantUriPermissionLocked () Permissão para chamar a Atividade apontada pelo objeto de intenção.Se
houver permissão, o ActivityManagerService verificará e iniciará a atividade de destino em uma nova tarefa
Etapa 3: Verifique se o ProcessRecord desse processo existe.Se existir, inicie a atividade diretamente, se ProcessRecord for nulo , ActivityManagerService criará um novo processo para instanciar a atividade de destino
Etapa 4: ActivityManagerService chama o método startProcessLocked () para criar um novo processo.Este método passará parâmetros para o processo Zygote através do canal de soquete mencionado acima. O método ZygoteInit.main () para instanciar o objeto ActivityThread e, finalmente, retornar o pid do novo processo
ActivityThread, em seguida, chame Looper.prepareLoop () e Looper.loop () por sua vez, para iniciar o loop da mensagem
Etapa 5: vincular o processo ao aplicativo especificado
Etapa 6: Chame realStartActivity () no processo existente para iniciar a atividade

2. Método de inicialização do aplicativo

(1) partida a frio

O aplicativo não foi iniciado ou o processo do aplicativo foi eliminado. O processo do aplicativo não existe no sistema. No momento, iniciar o aplicativo é uma partida a frio. O
processo de inicialização a frio é todo o processo do processo de inicialização do aplicativo descrito na Seção 2. É necessário criar um processo do aplicativo recursos de carregamento, comece fio principal, inicializar a primeira atividade da tela, etc.
neste processo, a tela irá mostrar uma janela em branco (com base no tema cor), até a primeira atividade da tela totalmente iniciado.
linha do tempo de partida a frio:
Insira a descrição da imagem aqui

(2) Começo quente

O início a quente significa que o processo do seu aplicativo está apenas em segundo plano, o sistema apenas o leva do segundo plano para o primeiro plano e o mostra ao usuário.
Semelhante ao início a frio, durante esse processo, a tela exibirá uma janela em branco (cor com base no tema), Até que a atividade seja renderizada.

(3) começo quente

Entre partida a frio e partida a quente, geralmente ocorre nas duas situações a seguir:
a) O usuário volta a sair do aplicativo e inicia novamente.O processo do aplicativo ainda pode estar em execução, mas a atividade precisa ser reconstruída
B. O usuário sai do aplicativo Depois disso, o sistema pode interromper o aplicativo devido à memória e processos e atividades precisam ser reiniciados, mas o estado da instância salva pode ser restaurado no onCreate.

Através da descrição dos três estados de inicialização, podemos ver que a otimização de inicialização que vamos fazer é realmente para inicialização a frio.A inicialização a quente e a quente são relativamente rápidas.

3. Razões para iniciar lentamente o aplicativo

De acordo com o gráfico de horário de início frio, podemos ver que, para o aplicativo, podemos controlar o ponto da linha do horário de início nada mais do que:
(3.1) Aplicativo onCreate
(3.2) a renderização da primeira atividade da tela
e nosso aplicativo atual está integrado Muitos serviços de terceiros precisam verificar anúncios, status de registro etc. na inicialização. Uma série de interfaces é feita no Application onCreate ou onCreate na primeira tela.

4. Análise de caso

(1) Análise de código

Como esse aplicativo integra serviços como Bugly, Push, Feedback e outros, o Application onCreate tem muito trabalho de inicialização para plataformas de terceiros:

public class GithubApplication extends MultiDexApplication {

    @Override
    public void onCreate() {
        super.onCreate();

        // init logger.
        AppLog.init();

        // init crash helper
        CrashHelper.init(this);

        // init Push
        PushPlatform.init(this);

        // init Feedback
        FeedbackPlatform.init(this);

        // init Share
        SharePlatform.init(this);

        // init Drawer image loader
        DrawerImageLoader.init(new AbstractDrawerImageLoader() {
            @Override
            public void set(ImageView imageView, Uri uri, Drawable placeholder) {
                ImageLoader.loadWithCircle(GithubApplication.this, uri, imageView);
            }
        });
    }
}

(2) O uso do Traceview para analisar o aplicativo onCreate leva tempo

Em seguida, combinamos nosso conhecimento teórico acima e a ferramenta Traceview introduzida para analisar o demorado aplicativo onCreate.Marque o
rastreio no início e no final do onCreate.

Debug.startMethodTracing("GithubApp");
...
Debug.stopMethodTracing();

A execução do programa gerará um arquivo "GithubApp.trace" no sdcard.

Nota: Você precisa adicionar a permissão para gravar armazenamento no programa:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Exporte para local via adb pull

adb pull /sdcard/GithubApp.trace ~/temp

Abra o arquivo de rastreio de análise DDMS.
ddms_open_trace
Analise o arquivo de rastreio
Insira a descrição da imagem aqui
. Clique em "Real Time / Call" na área de método abaixo e classifique o tempo em ordem decrescente de acordo com a chamada de método.
Demora mais de 500ms para prestar atenção.
Olhando para o nome do método à esquerda, você pode ver O grande usuário demorado é o método de inicialização de várias plataformas principais que usamos, principalmente o Bugly, que também carrega a lib nativa, opera com ZipFile etc.
Clique em cada método, você pode ver o método pai (chame) e todos os métodos filhos (É chamado.) Quando você
clica em um método, o eixo do tempo de execução do método acima pisca, você pode ver o encadeamento de execução e a duração relativa do método.

(3) OnCreate otimização de aplicativo

Coloque a inicialização do SDK de terceiros em um thread separado. Aqui, um InitializeService IntentService é usado para executar o trabalho de inicialização (o IntentService é diferente do Service, funciona no encadeamento em segundo plano.) O
código InitializeService.java é o seguinte:

public class InitializeService extends IntentService {

    private static final String ACTION_INIT_WHEN_APP_CREATE = "com.anly.githubapp.service.action.INIT";

    public InitializeService() {
        super("InitializeService");
    }

    public static void start(Context context) {
        Intent intent = new Intent(context, InitializeService.class);
        intent.setAction(ACTION_INIT_WHEN_APP_CREATE);
        context.startService(intent);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        if (intent != null) {
            final String action = intent.getAction();
            if (ACTION_INIT_WHEN_APP_CREATE.equals(action)) {
                performInit();
            }
        }
    }

    private void performInit() {
        AppLog.d("performInit begin:" + System.currentTimeMillis());

        // init Drawer image loader
        DrawerImageLoader.init(new AbstractDrawerImageLoader() {
            @Override
            public void set(ImageView imageView, Uri uri, Drawable placeholder) {
                ImageLoader.loadWithCircle(getApplicationContext(), uri, imageView);
            }
        });

        // init crash helper
        CrashHelper.init(this.getApplicationContext());

        // init Push
        PushPlatform.init(this.getApplicationContext());

        // init Feedback
        FeedbackPlatform.init(this.getApplication());

        // init Share
        SharePlatform.init(this.getApplicationContext());

        AppLog.d("performInit end:" + System.currentTimeMillis());
    }
}

Altere o onCreate do GithubApplication para:

public class GithubApplication extends MultiDexApplication {

    @Override
    public void onCreate() {
        super.onCreate();

        // init logger.
        AppLog.init();

        InitializeService.start(this);
    }
}

(4) Otimização da interface de inicialização

Etapa 1: criar um tema com plano de fundo

<style name="SplashTheme" parent="AppTheme">
    <item name="android:windowBackground">@drawable/logo_splash</item>
</style>

Etapa 2: use uma atividade que não renderize o layout como a tela de inicialização e adicione o tema

public class LogoSplashActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // 注意, 这里并没有setContentView, 单纯只是用来跳转到相应的Activity.
        // 目的是减少首屏渲染
        
        if (AppPref.isFirstRunning(this)) {
            IntroduceActivity.launch(this);
        }
        else {
            MainActivity.launch(this);
        }
        finish();
    }
}
<activity
  android:name=".ui.module.main.LogoSplashActivity"
  android:screenOrientation="portrait"
  android:theme="@style/SplashTheme">
  <intent-filter>
      <action android:name="android.intent.action.MAIN"/>
      <category android:name="android.intent.category.LAUNCHER"/>
  </intent-filter>
</activity>

5. Resumo

(1) Não faça muito no Application onCreate.
(2) A primeira tela de Atividade deve ser simplificada o máximo possível.
(3) Faça bom uso das ferramentas de análise de desempenho para análise.

Publicado 74 artigos originais · ganhou 15 · visualizações 6255

Acho que você gosta

Origin blog.csdn.net/qq_29966203/article/details/90473664
Recomendado
Clasificación