Diretório do artigo
- 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
- (2) Otimização da velocidade inicial
- 1. Análise do processo de inicialização do aplicativo Android
- 2. Método de inicialização do aplicativo
- 3. Razões para iniciar lentamente o aplicativo
- 4. Análise de caso
- (1) Análise de código
- (2) O uso do Traceview para analisar o aplicativo onCreate leva tempo
- (3) OnCreate otimização de aplicativo
- (4) Otimização da interface de inicialização
- 5. Resumo
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
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:
(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.
Analise o arquivo de rastreio
. 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.