一个App的程序入口到底是什么?

简介: 一个App的程序入口到底是什么?

一个App的程序入口到底是什么?

是ActivityThread.main()。

整个App的主线程的消息循环是在哪里创建的?

是在ActivityThread初始化的时候,就已经创建消息循环了,所以在主线程里面创建Handler不需要指定Looper,而如果在其他线程使用Handler,则需要单独使用Looper.prepare()和Looper.loop()创建消息循环。

public static void main(String[] args) {
          ...ignore some code...    
      Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        AsyncTask.init();
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
        Looper.loop();
          ...ignore some code...    
 }

Application是在什么时候创建的?onCreate()什么时候调用的?

也是在ActivityThread.main()的时候,再具体点呢,就是在thread.attach(false)的时候。

看你的表情,不信是吧!

我们先看一下ActivityThread.attach()

private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        //普通App进这里
        if (!system) {
            ...ignore some code...    
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
           } else {
             //这个分支在SystemServer加载的时候会进入,通过调用
             // private void createSystemContext() {
             //    ActivityThread activityThread = ActivityThread.systemMain();
             //} 
             // public static ActivityThread systemMain() {
        //        if (!ActivityManager.isHighEndGfx()) {
        //            HardwareRenderer.disable(true);
        //        } else {
        //            HardwareRenderer.enableForegroundTrimming();
        //        }
        //        ActivityThread thread = new ActivityThread();
        //        thread.attach(true);
        //        return thread;
        //    }       
           }
    }

这里需要关注的就是mgr.attachApplication(mAppThread),这个就会通过Binder调用到AMS里面对应的方法

@Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

然后就是

private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
             thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                    profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
                    mCoreSettingsObserver.getCoreSettingsLocked());
            }

thread是IApplicationThread,实际上就是ApplicationThread在服务端的代理类ApplicationThreadProxy,然后又通过IPC就会调用到ApplicationThread的对应方法

private class ApplicationThread extends ApplicationThreadNative {
  public final void bindApplication(String processName, ApplicationInfo appInfo,
                List<ProviderInfo> providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
                Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
                Bundle coreSettings) {
                 ...ignore some code...    
             AppBindData data = new AppBindData();
            data.processName = processName;
            data.appInfo = appInfo;
            data.providers = providers;
            data.instrumentationName = instrumentationName;
            data.instrumentationArgs = instrumentationArgs;
            data.instrumentationWatcher = instrumentationWatcher;
            data.instrumentationUiAutomationConnection = instrumentationUiConnection;
            data.debugMode = debugMode;
            data.enableOpenGlTrace = enableOpenGlTrace;
            data.restrictedBackupMode = isRestrictedBackupMode;
            data.persistent = persistent;
            data.config = config;
            data.compatInfo = compatInfo;
            data.initProfilerInfo = profilerInfo;
            sendMessage(H.BIND_APPLICATION, data);
           }
}

我们需要关注的其实就是最后的sendMessage(),里面有函数的编号H.BIND_APPLICATION,然后这个Messge会被H这个Handler处理

private class H extends Handler {
      ...ignore some code... 
     public static final int BIND_APPLICATION        = 110;
    ...ignore some code... 
     public void handleMessage(Message msg) {
          switch (msg.what) {
        ...ignore some code... 
         case BIND_APPLICATION:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                    AppBindData data = (AppBindData)msg.obj;
                    handleBindApplication(data);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
        ...ignore some code... 
        }
 }

最后就在下面这个方法中,完成了实例化,然后通过mInstrumentation.callApplicationOnCreate实现了onCreate()的调用。

private void handleBindApplication(AppBindData data) {
 try {
           ...ignore some code... 
            Application app = data.info.makeApplication(data.restrictedBackupMode, null);
            mInitialApplication = app;
           ...ignore some code... 
            try {
                mInstrumentation.onCreate(data.instrumentationArgs);
            }
            catch (Exception e) {
            }
            try {
                mInstrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {            }
        } finally {
            StrictMode.setThreadPolicy(savedPolicy);
        }
 }

data.info是一个LoadeApk对象。

LoadeApk.data.info.makeApplication()
 public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }
        Application app = null;
        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }
        try {
            java.lang.ClassLoader cl = getClassLoader();
            if (!mPackageName.equals("android")) {
                initializeJavaContextClassLoader();
            }
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;
    //传进来的是null,所以这里不会执行,onCreate在上一层执行
        if (instrumentation != null) {
            try {
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
            }
        }
        ...ignore some code... 
       }
        return app;
    }

所以最后还是通过Instrumentation.makeApplication()实例化的,这个老板娘真的很厉害呀!

static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = (Application)clazz.newInstance();
        app.attach(context);
        return app;
    }


相关文章
|
1月前
|
安全 开发工具 数据安全/隐私保护
如何将应用程序发布到 App Store
如何将应用程序发布到 App Store
|
2月前
|
安全 开发工具 数据安全/隐私保护
如何将应用程序发布到 App Store
如何将应用程序发布到 App Store
|
3月前
|
小程序 Linux 区块链
Python PyInstaller 打包成 Win、Mac 应用程序(app / exe)
Python PyInstaller 打包成 Win、Mac 应用程序(app / exe)
73 0
|
1月前
|
Android开发 iOS开发 开发者
点击APP的应用程序图标后,发生了什么
点击APP的应用程序图标后,发生了什么
|
2月前
|
PHP
HYBBS 表白墙网站PHP程序源码 可封装成APP
HYBBS 表白墙网站PHP程序源码 可封装成APP
28 1
|
7月前
|
移动开发 安全 数据安全/隐私保护
如何将应用程序发布到 App Store
在强者的眼中,没有最好,只有更好。我们是移动开发领域的优质创作者,同时也是阿里云专家博主。 ✨ 关注我们的主页,探索 iOS 开发的无限可能! 🔥我们与您分享最新的技术洞察和实战经验,助您在移动应用开发领域取得成功。 📌欢迎访问我们的微信公众号:憧憬 blog,获取更多精彩内容、实用技巧、行业资讯等。您关注的是我们前进的动力! 💼我们还担任阿里云专家博主的角色,为您提供更深入的技术指导和解答疑点。 🌟期待与您一起在移动开发的世界中,不断进步和创造! 🙏感谢您对我们的支持和关注!请继续关注我们的主页,获取更多精彩内容!
|
4月前
如果稀土掘金App要更新“发布文章”功能,那么入口会设置在哪里?
如果稀土掘金App要更新“发布文章”功能,那么入口会设置在哪里?
25 0
|
5月前
|
存储 前端开发 JavaScript
潮玩元宇宙大逃杀app游戏系统开发稳定版/流程设计/功能步骤/需求逻辑/源码程序
需求分析:明确项目的整体目标和功能需求,包括游戏规则、玩法机制、图形界面、用户账号系统、实时交互等。
|
6月前
|
存储 安全 API
阿里云APP下载入口和方式
阿里云APP是一款为用户提供安全、稳定、高效的云计算服务的手机应用程序。它具备多种功能,包括文件存储、文件共享、远程控制、备份等等。下面从背景介绍、概览、价值、竞品对比分析、可靠性、创新性、用户反馈和影响力等方面展开扩写。
阿里云APP下载入口和方式
|
6月前
|
移动开发 小程序
外卖霸王餐系统程序 美团/饿了么霸王餐系统,支持小程序/APP/H5/公众号
微客云免费提供外卖霸王餐系统,支持分站、运营商、商家后台、独立域名,自定义品牌,自主收款。
93 0