Capítulo ocho Optimización del rendimiento Optimización de inicio de la aplicación (2)

Capítulo ocho Optimización del rendimiento Optimización de inicio de la aplicación (2)

(1) Pantalla de inicio pantalla blanca / resolución de pantalla negra

1. Fenómeno

Cuando abra la aplicación, a menudo hará una pausa antes de ingresar a la página de inicio (Splash)

2. Razón

En el método onCreate () para iniciar Acitivty, el sistema dibuja primero el formulario y luego ejecuta setContentView (R.layout.activity_splash). Después de que se dibuja el formulario, los recursos de diseño no se han cargado, por lo que se utiliza el color de fondo predeterminado.
Si el tema usa Theme.AppCompat.Light (sistema de color claro), muestra una pantalla de bienvenida blanca, si usa ThemeOverlay.AppCompat.Dark (sistema de color oscuro), muestra una pantalla de bienvenida negra.

3. Resolver

Paso 1: configure la imagen de inicio bg_splash como fondo del formulario, para evitar la aparición cuando se inicia la aplicación, pantalla en blanco y negro
Paso 2: cuando se configura como pantalla de fondo bg_splash, el fondo es responsable de cargar recursos y descargar la imagen publicitaria, descargar la imagen publicitaria Muestre la apariencia real de SplashActivity cuando el éxito o el tiempo de espera
Paso 3: Ingrese 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) Optimización de la velocidad de arranque

1. Análisis del proceso de inicio de aplicaciones de Android

(1) Teoría básica de la aplicación

Cada aplicación de Android se encuentra en un espacio separado, lo que significa que se ejecuta en un proceso separado, tiene su propia máquina virtual y el sistema le asigna un ID de usuario único. La
aplicación de Android consta de muchos componentes diferentes, que también pueden iniciar otros Componentes de la aplicación. Por lo tanto, la aplicación de Android no tiene un método main () similar a la entrada del programa. El
proceso de Android es el mismo que el proceso de Linux. Por defecto, cada apk se ejecuta en su propio proceso de Linux. Además, solo hay uno en el proceso predeterminado. Subproceso: el subproceso principal. Hay una instancia de Looper en este subproceso principal, y el mensaje se recupera de la cola de mensajes llamando a Looper.loop () para el procesamiento correspondiente. El
proceso se inicia cuando es necesario. En cualquier momento, cuando el usuario u otros componentes Cuando llama a cualquiera de los componentes de su apk, si su apk no se está ejecutando, el sistema creará un nuevo proceso para él y lo iniciará. Por lo general, este proceso continuará ejecutándose hasta que el sistema lo elimine.

(2) Proceso de inicio de la aplicación

Inserte la descripción de la imagen aquí
Cuando el usuario hace clic en el ícono de una aplicación en el Inicio para iniciar una aplicación: el
evento Click llamará a startActivity (Intent), Launcer usará el mecanismo Binder IPC y finalmente notificará a ActivityManagerService (AMS es un proceso del sistema Android, utilizado para administrar la operación de los cuatro componentes principales del sistema Estado) para iniciar la Actividad.
El Servicio realizará las siguientes operaciones: El
primer paso: recopilar la información de puntería de este objeto de intención a través del resolveIntent () de PackageManager. La información de puntería se almacena en un objeto de intención. El
segundo paso: verificar si el usuario tiene suficiente mediante grantUriPermissionLocked () Permiso para llamar a la Actividad señalada por el objeto de intención.
Si hay permiso, ActivityManagerService verificará e iniciará la actividad objetivo en una nueva tarea
Paso 3: Verifique si el ProcessRecord de este proceso existe. Si existe, inicie la actividad directamente, si ProcessRecord es nulo , ActivityManagerService creará un nuevo proceso para crear una instancia de la actividad objetivo
. Paso 4: ActivityManagerService llama al método startProcessLocked () para crear un nuevo proceso. Este método pasará parámetros al proceso Zygote a través del canal de socket mencionado anteriormente. Zygote se incuba y llama Método ZygoteInit.main () para instanciar el objeto ActivityThread y finalmente devolver el pid del nuevo proceso
ActivityThread y luego llamar a Looper.prepareLoop () y Looper.loop () para iniciar el bucle de mensajes
Paso 5: enlace el proceso con la aplicación especificada
Paso 6: llame a realStartActivity () en el proceso existente para iniciar la actividad

2. Método de inicio de la aplicación

(1) arranque en frío

La aplicación no se ha iniciado o el proceso de la aplicación se ha cancelado. El proceso de la aplicación no existe en el sistema. En este momento, el inicio de la aplicación es un inicio en frío. El
proceso de inicio en frío es todo el proceso del proceso de inicio de la aplicación que se describe en la Sección 2. Es necesario crear un proceso de la aplicación recursos de carga, iniciar el subproceso principal, inicializar la primera actividad de la pantalla, etc.
en este proceso, la pantalla mostrará una ventana en blanco (basado en el tema del color), hasta que la primera actividad de la pantalla completamente encendido.
arranque en frío línea de tiempo:
Inserte la descripción de la imagen aquí

(2) arranque en caliente

El inicio en caliente significa que el proceso de su aplicación está solo en segundo plano, el sistema simplemente lo toma del fondo al primer plano y se lo muestra al usuario.
Similar al inicio en frío, durante este proceso, la pantalla mostrará una ventana en blanco (color basado en el tema), Hasta que se realice la actividad.

(3) inicio cálido

Entre el arranque en frío y el arranque en caliente, generalmente ocurre en las siguientes dos situaciones:
a. El usuario vuelve a cerrar la aplicación, y luego comienza de nuevo. El proceso de la aplicación aún puede estar ejecutándose, pero la actividad necesita ser reconstruida.
B. El usuario cierra la aplicación Después de eso, el sistema puede matar la aplicación debido a la memoria, y tanto los procesos como las actividades deben reiniciarse, pero el estado de la instancia guardada se puede restaurar en onCreate.

A través de la descripción de los tres estados de inicio, podemos ver que la optimización de inicio que vamos a hacer es en realidad para el inicio en frío. Tanto el inicio en caliente como el en caliente son relativamente rápidos.

3. Razones para el inicio lento de la aplicación

De acuerdo con el gráfico de tiempo de inicio en frío, podemos ver que para la aplicación, podemos controlar el punto de la línea de tiempo de inicio nada más que:
(3.1) Aplicación onCreate
(3.2) la representación de la actividad de la primera pantalla
y nuestra aplicación actual está integrada Muchos servicios de terceros necesitan verificar anuncios, estado de registro, etc. al inicio. Una serie de interfaces se realizan en onCreate of Application o onCreate de la primera pantalla.

4. Análisis de casos

(1) Análisis de código

Debido a que esta aplicación integra servicios como Bugly, Push, Feedback, etc., Application onCreate tiene mucho trabajo de inicialización para plataformas de terceros:

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) Usar Traceview para analizar la aplicación onCreate lleva tiempo

A continuación, combinamos nuestro conocimiento teórico anterior y la herramienta Traceview introducida para analizar la aplicación onCreate, que requiere mucho tiempo. Marque el
seguimiento al principio y al final de onCreate.

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

La ejecución del programa generará un archivo "GithubApp.trace" en la tarjeta sd.

Nota: debe agregar el permiso para escribir almacenamiento en el programa:

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

Exportarlo a local mediante adb pull

adb pull /sdcard/GithubApp.trace ~/temp

Abra el archivo de seguimiento de análisis DDMS.
ddms_open_trace
Analice el archivo de seguimiento
Inserte la descripción de la imagen aquí
. Haga clic en "Tiempo real / Llamada" en el área del método a continuación, y ordene el tiempo en orden descendente de acuerdo con la llamada al método. Se
requieren más de 500 ms para prestar atención.
Al observar el nombre del método a la izquierda, puede ver El gran usuario que consume tiempo es el método de inicialización de varias plataformas principales que utilizamos, especialmente Bugly, también carga la biblioteca nativa, funciona con ZipFile, etc.
Haga clic en cada método, puede ver su método principal ( llámelo ) y todos sus métodos secundarios. (Se llama). Cuando hace
clic en un método, el eje de tiempo de ejecución del método anterior parpadeará, puede ver el hilo de ejecución y la duración relativa del método.

(3) Optimización OnCreate de la aplicación

Coloque la inicialización del SDK de terceros en un hilo separado. Aquí se utiliza un InitializeService IntentService para realizar el trabajo de inicialización (IntentService es diferente del Servicio, funciona en el subproceso de fondo). El
código InitializeService.java es el siguiente:

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());
    }
}

Cambie onCreate of GithubApplication a:

public class GithubApplication extends MultiDexApplication {

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

        // init logger.
        AppLog.init();

        InitializeService.start(this);
    }
}

(4) Optimización de la interfaz de inicio

Paso 1: crea un tema con fondo

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

Paso 2: utilice una actividad que no muestre el diseño como pantalla de inicio y agregue el 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. Resumen

(1) No haga demasiado en Application onCreate.
(2) La actividad de la primera pantalla debe simplificarse tanto como sea posible.
(3) Haga un buen uso de las herramientas de análisis de rendimiento para el análisis.

Publicado 74 artículos originales · ganó 15 · vistas 6255

Supongo que te gusta

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