Comment démarrer l'application Android App d'interprétation du code source ?

avant-propos

En tant que développeur Android depuis de nombreuses années, j'ai écrit de nombreuses applications, mais comment une application démarre-t-elle ? Si vous dites que le bureau démarre avec un clic, c'est vrai. Mais qu'en est-il de son processus de démarrage ? Avec de telles questions, apprenons étape par étape.

Processus de démarrage Android

Généralement, sur n'importe quelle plate-forme, les composants suivants sont chargés et exécutés de manière incrémentielle :

  • Chargeur de démarrage
  • U-boot (optionnel)
  • Noyau
  • Android

Les processus Android ont l'ordre suivant :

  • Init
  • Zygote
  • Serveur système
  • Gestionnaire de services
  • Autres démons et processus
  • Applications

La situation spécifique est la suivante, et il est intéressant de combiner ces deux images :

image.png

  • Boot ROM : Lorsque l'alimentation est enfoncée, le code de la puce de démarrage commence à s'exécuter à partir d'un emplacement prédéfini (solidifié dans la ROM), charge le programme de démarrage BootLoader sur la RAM, puis s'exécute. (Cette étape est conçue et mise en œuvre par le "fabricant de puce")

  • Chargeur de démarrage : Bootloader commence à s'exécuter, tout d'abord, il est chargé de terminer l'initialisation du matériel et de démarrer le système d'exploitation pour démarrer. (Cette étape est conçue et mise en œuvre par le "fabricant de l'équipement")

  • Noyau : Le noyau Linux est le noyau d'Android, responsable de la création de processus, de la communication inter-processus, des pilotes de périphériques, de la gestion du système de fichiers, etc. Android applique des correctifs personnalisés sur le noyau principal pour prendre en charge certaines fonctionnalités nécessaires à l'exécution d'Android, telles que les wakelocks. Les noyaux peuvent être chargés sous forme d'images non compressées ou compressées. Au chargement, il monte le système de fichiers racine (généralement passé en argument de ligne de commande du noyau) et démarre la première application dans l'espace utilisateur . (Cette étape est ce qui doit être impliqué dans le processus de développement du noyau Android)

  • Android : système Android et principales distributions Linux, leur noyau Linux faisant partie du processus de démarrage est similaire, la plus grande différence entre eux est la différence dans le programme init, car le programme init détermine le système pendant le processus de démarrage, ce qui se passera Quels démons et les services sont démarrés, et quel type d'interface utilisateur est présenté.

Par conséquent, le programme init est le programme le plus important pour analyser le processus de démarrage d'Android.

  • init et init.rc : La première application en espace utilisateur exécutée au démarrage du noyau est l'exécutable init situé dans le dossier racine. Le processus analyse un script de démarrage appelé le script "init.rc". Ceci est écrit dans un langage conçu pour Android pour démarrer tous les processus, démons et services nécessaires au bon fonctionnement d'Android. Il fournit différents types de temps d'exécution tels que early-init, on-boot, on-post-fs, etc. (le créateur de l'espace utilisateur)

  • Démons et services : Le processus init crée divers démons et processus, tels que rild, vold, mediaserver, adb, etc., chaque processus est responsable de ses propres fonctions. Une description de ces processus dépasse le cadre de cet article. Au lieu de cela, nous parlerons davantage du processus "Zygote".

  • Service Manager : Le processus Service Manager gère tous les services en cours d'exécution dans le système. Chaque service créé s'enregistre dans ce processus et ces informations sont destinées à être consultées ultérieurement par d'autres processus/applications.

  • Zygote : Zygote est l'un des premiers processus d'initialisation créé au démarrage. Le terme "zygote" est basé sur la "formation biologique d'une division cellulaire initiale pour produire une progéniture". De même, « zygote dans Android » initialise la machine virtuelle Dalivik (ART) et bifurque pour créer plusieurs instances pour prendre en charge chaque processus Android. Il facilite l'utilisation de code partagé entre les instances de VM, réduisant l'empreinte mémoire et le temps de chargement, ce qui le rend idéal pour les systèmes embarqués. En plus d'installer un écouteur sur le socket du serveur, Zygote précharge également des classes et des ressources pour une utilisation ultérieure dans l'application Android. Une fois terminé, le serveur système démarre.

  • System Server : Le processus SystemServer démarre tous les services disponibles dans Android.

Dans cet article, nous nous concentrons sur le démarrage de l'initialisation au démarrage de l'application.

1. Qu'est-ce que Zygote ?

Dans le système Android, zygote est le nom d'un processus. Android est basé sur le système Linux. Lorsque votre téléphone est allumé, un processus appelé "init" sera lancé après le chargement du noyau Linux. Dans le système Linux, tous les processus sont dupliqués par le processus init , et notre processus zygote ne fait pas exception.

Zygote est un processus de machine virtuelle et un incubateur d'instances de machines virtuelles. Chaque fois que le système demande d'exécuter une application Android, Zygote bifurque (divise) un processus enfant pour exécuter l'application.

1.1 app_main.cpp

frameworks/base/cmds/app_process/app_main.cpp

app_main.cpp est exécuté après le démarrage de Zygote. Qu'il s'agisse de C/c++/java, leur entrée est main(), tout comme lorsque nous voyons Activity, nous recherchons directement la méthode onCreate().

1.1.1 principal()

int main(int argc, char* const argv[])
{
    ...
    //注释1:初始化AppRuntime(AndroidRunTime)
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    ...
    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        //注释2:设置zygote模式
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } 
        ...
    }
    Vector<String8> args;
    if (!className.isEmpty()) {
        ...
    } else {
        // 我们处于 zygote 模式。
        maybeCreateDalvikCache();

        // 注释3:在 zygote 模式下,将参数传递给 ZygoteInit.main() 方法。
        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }

        //PROP_VALUE_MAX = 92;
        char prop[PROP_VALUE_MAX];
        ...
        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);

        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }    
    if (zygote) {
        //注释4:调用 AndroidRuntime.start() 方法
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        ...
    } else {
        ...
    }
}

Remarque 1 : Initialisez AppRuntime, qui est en fait AndroidRuntime (ART).

Remarque 2 : Définissez le mode zygote.

Remarque 3 : Transmettez les paramètres à la méthode ZygoteInit.main().

Remarque 4 : Démarrez ZygoteInit. ZygoteInit est ici la classe de démarrage du processus zygote. Ceci est mentionné ci-dessous. Regardons d'abord la méthode start() d'AndroidRuntime.

1.2 AndroidRuntime.cpp

frameworks/base/core/jni/AndroidRuntime.cpp

Machine virtuelle Android

1.2.1 début()

/*
 * Start the Android runtime.  This involves starting the virtual machine and calling the "static void main(String[] args)" method in the class named by "className".
 *
 * Passes the main function two arguments, the class name and the specified
 * options string.
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ...
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    //注释1:启动虚拟机
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    onVmCreated(env);

    //注释2:注册安卓功能(JNI)
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
    ...
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    ...
    /*
     * 启动虚拟机。 该线程成为VM的主线程,直到VM退出才会返回。
     */
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ...
    } else {
        ...
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ...
        } else {
            //注释3
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
        }
    }
    ...
}
复制代码

Remarque 1 : Démarrez la VM (Virtual Machine)

Remarque 2 : enregistrement des fonctions Android (JNI)

Remarque 3 : Utilisez JNI pour appeler la méthode main() de Zygotelnit. Zygotelnit ici est un fichier de classe, c'est-à-dire qu'il entre dans le champ java à partir d'ici.

JNI : un pont reliant la couche native (C/C++) et la couche Java.

1.3 ZygoteInit.java

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

/**
 * zygote 进程的启动类。
 */
public class ZygoteInit {
    ...
}
复制代码

C'est le point d'entrée du processus Zygote. Il crée des services Zygote, charge des ressources et gère d'autres tâches liées au processus de préparation du fork dans une application.

1.3.1 principal()

    @UnsupportedAppUsage
    public static void main(String[] argv) {
        ZygoteServer zygoteServer = null;

        try {
            ...
            boolean startSystemServer = false;
            //argv:用于指定 Zygote 配置的命令行参数。
            ...
            if (!enableLazyPreload) {
                //注释1:预加载资源。
                preload(bootTimingsTraceLog);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                        SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            }
            ...
            //注释2:创建Zygote 的 LocalServerSocket 。
            zygoteServer = new ZygoteServer(isPrimaryZygote);

            if (startSystemServer) {
                //注释3:开始fork我们的SystemServer进程。
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
                ...
            }
            ...
            // 注释4:zygote 永久循环。
            caller = zygoteServer.runSelectLoop(abiList);            
        } catch (Throwable ex) {
            ...
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }
        ...
    }
复制代码

Remarque 1 : préchargez les ressources.

Remarque 2 : Créez le LocalServerSocket de Zygote.

Remarque 3 : commencez à bifurquer notre processus SystemServer.

Remarque 4 : boucles zygote pour toujours.

Ici, nous regardons forkSystemServer();

1.3.2 forkSystemServer ()

    /**
     * Prepare the arguments and forks for the system server process.
     *
     * @return A {@code Runnable} that provides an entrypoint into system_server code in the child
     * process; {@code null} in the parent.
     */
    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        ...
        //命令行来启动SystemServer
        //ZygoteInit.main(String argv[])里面的argv 跟这个类似
        String[] args = {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
                        + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer",
        };
        //处理与 zygote spawner 相关的 args 的参数解析。
        ZygoteArguments parsedArgs;
        int pid;
        try {
            ZygoteCommandBuffer commandBuffer = new ZygoteCommandBuffer(args);
            try {
                parsedArgs = ZygoteArguments.getInstance(commandBuffer);
            } catch (EOFException e) {
                throw new AssertionError("Unexpected argument error for forking system server", e);
            }
            commandBuffer.close();
            ...

            //请求 fork 系统服务器进程
            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }
复制代码

Un serveur système est démarré ici. Jetons un coup d'œil à lui ci-dessous.

2、SystemServer

serveur système est également SystemServer. SystemServer est également un processus, comprenant 92 services tels que ActivityTaskManagerService, ActivityManagerService, PackageManagerService et WindowManagerService.

Il existe deux processus très importants dans le Framework Android :

  • Processus SystemServer.

  • Processus zygote.

2.1 SystemServer.java

frameworks/base/services/java/com/android/server/SystemServer.java

public final class SystemServer {
    ...
}
复制代码

2.1.1 principal()

    /**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }
    public SystemServer() {
        // Check for factory test mode.
        mFactoryTestMode = FactoryTest.getMode();
        ...
    }    
复制代码

Voyons ce qui est utilisé dans run()?

2.1.2 exécuter()

    private void run() {
        try {
            ...
            // 注释1:加载动态库libandroid_service.so。
            System.loadLibrary("android_servers");

            // 注释2:创建系统上下文。
            createSystemContext();

            // 调用每个进程的主线模块初始化。
            ActivityThread.initializeMainlineModules();

            // 注释3:创建 SystemServiceManager。
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setStartInfo(mRuntimeRestart,
                    mRuntimeStartElapsedTime, mRuntimeStartUptime);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            // 为可并行化的 init 任务准备线程池
            SystemServerInitThreadPool.start();
            ...
        } finally {

        }
        // 注释4:Start services。
        try {
            //下面咱们看看这个三个方法启动什么服务
            startBootstrapServices(t);
            startCoreServices(t);
            startOtherServices(t);
        } catch (Throwable ex) {
            ...
        } finally {
            t.traceEnd(); // StartServices
        }

        ...
        // 注释5:Loop 永久循环。
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

复制代码

Remarque 1 : Chargez la bibliothèque dynamique libandroid_service.so.

Remarque 2 : créez un contexte système.

Remarque 3 : créez SystemServiceManager.

Remarque 4 : Démarrer les services (startBootstrapServices, startCoreServices, startOtherServices)

Remarque 5 : Loop loops indéfiniment.

2.1.3 createSystemContext()

    private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

        final Context systemUiContext = activityThread.getSystemUiContext();
        systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
    }
复制代码

Initialisez l'objet de contexte système mSystemContext et définissez le thème par défaut, mSystemContext est en fait un objet Context (ContextImpl).

Lorsque ActivityThread.systemMain() est appelé, ActivityThread.attach(true) est appelé, et dans attach(), l'objet Application est créé et Application.onCreate() est appelé.

2.1.4 startBootstrapServices()

    /**
     * 启动系统引导服务,因为这些服务之间有复杂的相互依赖关系,所以都放在了这个方法里面。
     */
    private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
        ...
        final String TAG_SYSTEM_CONFIG = "ReadingSystemConfig";
        SystemServerInitThreadPool.submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG);

        // PlatformCompat Service 由 ActivityManagerService, PackageManagerService 和 其他服务做使用
        PlatformCompat platformCompat = new PlatformCompat(mSystemContext);
        ServiceManager.addService(Context.PLATFORM_COMPAT_SERVICE, platformCompat);
        ServiceManager.addService(Context.PLATFORM_COMPAT_NATIVE_SERVICE,
                new PlatformCompatNative(platformCompat));
        AppCompatCallbacks.install(new long[0]);

        mSystemServiceManager.startService(FileIntegrityService.class);
        Installer installer = mSystemServiceManager.startService(Installer.class);
        mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
        mSystemServiceManager.startService(UriGrantsManagerService.Lifecycle.class);
        startMemtrackProxyService();

        // StartActivityManager
        ActivityTaskManagerService atm = mSystemServiceManager.startService(
                ActivityTaskManagerService.Lifecycle.class).getService();
        //初始化 ActivityManagerService
        mActivityManagerService = ActivityManagerService.Lifecycle.startService(
                mSystemServiceManager, atm);
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        mWindowManagerGlobalLock = atm.getGlobalLock();

        mDataLoaderManagerService = mSystemServiceManager.startService(
                DataLoaderManagerService.class);

        mIncrementalServiceHandle = startIncrementalService();
        t.traceEnd();

        //初始化PowerManagerService(电源服务),需要提前启动,因为其他服务需要它。
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
        mSystemServiceManager.startService(ThermalManagerService.class);

        // 电源管理已经开启,ActivityManagerService负责电源管理功能
        mActivityManagerService.initPowerManagement();

        mSystemServiceManager.startService(RecoverySystemService.Lifecycle.class);
        ...

        mSystemServiceManager.startService(LightsService.class);

        // Package manager isn't started yet; need to use SysProp not hardware feature
        if (SystemProperties.getBoolean("config.enable_sidekick_graphics", false)) {
            mSystemServiceManager.startService(WEAR_SIDEKICK_SERVICE_CLASS);
        }

        // 初始化DisplayManagerService(显示管理器)
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

        mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);

        // Start the package manager.
        try {
            mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        } finally {

        }

        // 现在PackageManagerService已经启动,注册 dex 加载报告器来捕获系统服务加载的任何 dex 文件。
        // 这些 dex 文件将由 BackgroundDexOptService 优化。
        SystemServerDexLoadReporter.configureSystemServerDexReporter(mPackageManagerService);

        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();
        ...
        //将AMS等添加到ServiceManager中
        mActivityManagerService.setSystemProcess();
        if (!mOnlyCore) {
            boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
                    false);
            if (!disableOtaDexopt) {
                try {
                    OtaDexoptService.main(mSystemContext, mPackageManagerService);
                } catch (Throwable e) {

                } finally {
                }
            }
        }

        ...
        mSensorServiceStart = SystemServerInitThreadPool.submit(() -> {
            TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog();
            startSensorService();
        }, START_SENSOR_SERVICE);

        // startBootstrapServices
    }
复制代码

Changements majeurs:

  • ActivityTaskManagerService(ATMS) : responsable de la gestion des activités et des processus, y compris le cycle de vie et le changement d'état.

  • ActivityManagerService (AMS) : une sous-classe d'AMN, responsable de la gestion de trois composants principaux (à l'exception de l'activité) et des processus, y compris le cycle de vie et la commutation d'état. AMS est extrêmement complexe car il doit interagir avec l'interface utilisateur, impliquant des fenêtres.

ActivityTaskManagerService : généré en supprimant le contenu lié à l'activité de ActivityManagerService.

PowerManagerService(PMS) : service de gestion de l'alimentation.

PackageManagerService(PKMS) : Le service de gestion des packages, non appelé PMS, est à distinguer du service de gestion de l'alimentation.

2.1.5 startCoreServices()

    /**
     * 启动核心服务。
     */
    private void startCoreServices(@NonNull TimingsTraceAndSlog t) {
        // Service for system config
        mSystemServiceManager.startService(SystemConfigService.class);
        // Tracks the battery level.  Requires LightService.
        mSystemServiceManager.startService(BatteryService.class);
        ...
        mSystemServiceManager.startService(LooperStatsService.Lifecycle.class);

        mSystemServiceManager.startService(ROLLBACK_MANAGER_SERVICE_CLASS);

        mSystemServiceManager.startService(NativeTombstoneManagerService.class);

        mSystemServiceManager.startService(BugreportManagerService.class);

        mSystemServiceManager.startService(GpuService.class);

        // startCoreServices
    }

复制代码

2.1.6 startAutresServices()

    /**
     * 启动其他服务。
     */
    private void startOtherServices(@NonNull TimingsTraceAndSlog t) {

        final Context context = mSystemContext;
        VibratorService vibrator = null;
        DynamicSystemService dynamicSystem = null;
        IStorageManager storageManager = null;
        NetworkManagementService networkManagement = null;
        IpSecService ipSecService = null;
        VpnManagerService vpnManager = null;
        VcnManagementService vcnManagement = null;
        NetworkStatsService networkStats = null;
        NetworkPolicyManagerService networkPolicy = null;
        NsdService serviceDiscovery = null;
        WindowManagerService wm = null;
        SerialService serial = null;
        NetworkTimeUpdateService networkTimeUpdater = null;
        InputManagerService inputManager = null;
        TelephonyRegistry telephonyRegistry = null;
        ConsumerIrService consumerIr = null;
        MmsServiceBroker mmsService = null;
        HardwarePropertiesManagerService hardwarePropertiesService = null;
        PacProxyService pacProxyService = null;
        ...
        // 现在便可以开始启动三方APP应用(如Launcher启动桌面)
        mActivityManagerService.systemReady(() -> {
        ...
         }, t);       
        // startOtherServices
    }
复制代码

Après les étapes ci-dessus, lorsque nous appelons createSystemContext() pour créer le contexte système, nous avons terminé la création de mSystemContext et ActivityThread.

Des objets tels que ATMS, AMS, WMS et PKMS ont été créés et des variables membres ont été initialisées.

Remarque : Il s'agit du processus au démarrage du processus système. Après cela, le système sera démarré.

Le programme Launcher termine le chargement et l'affichage de l'interface système.

Dans la conception du cadre d'Android, le côté serveur fait référence aux services système partagés par toutes les applications, telles que ATMS, AMS, WMS, PKMS, etc.. Ces services système de base sont partagés par toutes les applications.

3. Qu'est-ce que le lanceur

Dans le système Android, l'application est lancée par le lanceur. En fait, le lanceur lui-même est également une application . Après l'installation d'autres applications, une icône correspondante apparaîtra sur l'interface du lanceur. Lorsque vous cliquez sur cette icône, le lanceur l'application correspondante démarre.

Bien sûr, vous pouvez également démarrer des applications dans d'autres applications. Mais en substance, il appelle startActivity().

3.1 LauncherActivity.java

frameworks/base/core/java/android/app/LauncherActivity.java

/**
 * Displays a list of all activities which can be performed
 * for a given intent. Launches when clicked.
 *
 * @deprecated Applications can implement this UI themselves using
 *   {@link androidx.recyclerview.widget.RecyclerView} and
 *   {@link android.content.pm.PackageManager#queryIntentActivities(Intent, int)}
 */
@Deprecated
public abstract class LauncherActivity extends ListActivity {
    ...
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        Intent intent = intentForPosition(position);
        startActivity(intent);
    }
}
复制代码

résumé

Une photo complète est jointe

Si vous connaissez startActivity(), vous pouvez jeter un coup d'œil directement. Il y a tellement de contenu dans ce post que je suis irrité rien qu'en le regardant. Si vous ne l'avez pas vu, faites signe, et les détails seront expliqués dans le prochain article : ❤️ Analyse du code source d'Android startActivity ❤️.

Je suppose que tu aimes

Origine blog.csdn.net/ajsliu1233/article/details/120711444
conseillé
Classement