源码探探之startActivity(二)

源码基于API26
在上一篇中,讲到由ActivityThread启动activity了
ActivityThread即我们平时提到的主线程,上一篇中AMS处理启动activity的task和record信息后通过binder跨进程到应用当前线程继续启动activity
现在看ActivityThread的scheduleLaunchActivity()

@Override
    public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
            CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
            int procState, Bundle state, PersistableBundle persistentState,
            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
            boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
        //更新进程状态
        updateProcessState(procState, false);
        //创建ActivityClientRecord并赋值
        ActivityClientRecord r = new ActivityClientRecord();
        r.token = token;
        r.ident = ident;
        r.intent = intent;
        r.referrer = referrer;
        r.voiceInteractor = voiceInteractor;
        r.activityInfo = info;
        r.compatInfo = compatInfo;
        r.state = state;
        r.persistentState = persistentState;
        r.pendingResults = pendingResults;
        r.pendingIntents = pendingNewIntents;
        r.startsNotResumed = notResumed;
        r.isForward = isForward;
        r.profilerInfo = profilerInfo;
        r.overrideConfig = overrideConfig;
        updatePendingConfiguration(curConfig);
        //带着ActivityClientRecord由Handler启动Activity
        sendMessage(H.LAUNCH_ACTIVITY, r);
    }复制代码

接着看Handler

 public void handleMessage(Message msg) {
           ...
        switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                //handler传递过来的ActivityClientRecord
                final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
                //赋值LoadedApk
                r.packageInfo = getPackageInfoNoCheck(
                        r.activityInfo.applicationInfo, r.compatInfo);
                //继续启动activity
                handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            } break;复制代码

接着handleLaunchActivity()

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    //跳过后台执行gc
    unscheduleGcIdler();
    mSomeActivitiesChanged = true;
    if (r.profilerInfo != null) {
        mProfiler.setProfiler(r.profilerInfo);
        mProfiler.startProfiling();
    }
    // 确保执行最新的配置
    handleConfigurationChanged(null, null);
    if (localLOGV) Slog.v(
        TAG, "Handling launch of " + r);
    // 创建activity之前初始化WindowManagerGlobal,获取IWindowManger
    WindowManagerGlobal.initialize();
    //启动activity
    Activity a = performLaunchActivity(r, customIntent);
    //activity不为null
    if (a != null) {
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        Bundle oldState = r.state;
        //恢复activity
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
        if (!r.activity.mFinished && r.startsNotResumed) {
            performPauseActivityIfNeeded(r, reason);
            //pre-Honeycomb apps需要保存初始状态以便再次创建
            if (r.isPreHoneycomb()) {
                r.state = oldState;
            }
        }
    } else {
        //不管什么原因出错调用AMS销毁activity
        try {
            ActivityManager.getService()
                .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                        Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
}复制代码

接着performLaunchActivity()

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    //LoadedApk检验
    ActivityInfo aInfo = r.activityInfo;
    if (r.packageInfo == null) {
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                Context.CONTEXT_INCLUDE_CODE);
    }
    //component检验
    ComponentName component = r.intent.getComponent();
    if (component == null) {
        component = r.intent.resolveActivity(
            mInitialApplication.getPackageManager());
        r.intent.setComponent(component);
    }
    //原activity不为空可新建component
    if (r.activityInfo.targetActivity != null) {
        component = new ComponentName(r.activityInfo.packageName,
                r.activityInfo.targetActivity);
    }
    //创建contextImpl
    ContextImpl appContext = createBaseContextForActivity(r);
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = appContext.getClassLoader();
        //通过Instrumentation创建activity实例
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        r.intent.prepareToEnterProcess();
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to instantiate activity " + component
                + ": " + e.toString(), e);
        }
    }

    try {
        //创建我们亲爱的application
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
        if (localLOGV) Slog.v(
                TAG, r + ": app=" + app
                + ", appName=" + app.getPackageName()
                + ", pkg=" + r.packageInfo.getPackageName()
                + ", comp=" + r.intent.getComponent().toShortString()
                + ", dir=" + r.packageInfo.getAppDir());
        if (activity != null) {
            //加载label
            CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
            Configuration config = new Configuration(mCompatConfiguration);
            if (r.overrideConfig != null) {
                config.updateFrom(r.overrideConfig);
            }
            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                    + r.activityInfo.name + " with config " + config);
            Window window = null;
            if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                window = r.mPendingRemoveWindow;
                r.mPendingRemoveWindow = null;
                r.mPendingRemoveWindowManager = null;
            }
            //context表示为activity
            appContext.setOuterContext(activity);
            //准备好了吗我们的activity来了
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor, window, r.configCallback);
            if (customIntent != null) {
                activity.mIntent = customIntent;
            }
            r.lastNonConfigurationInstances = null;
            checkAndBlockForNetworkAccess();
            activity.mStartedActivity = false;
            int theme = r.activityInfo.getThemeResource();
            //设置主题
            if (theme != 0) {
                activity.setTheme(theme);
            }
            activity.mCalled = false;
            //activity已启动执行onCreate()了
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            if (!activity.mCalled) {
                throw new SuperNotCalledException(
                    "Activity " + r.intent.getComponent().toShortString() +
                    " did not call through to super.onCreate()");
            }
            r.activity = activity;
            r.stopped = true;
            //没有关闭就要执行onStart()了
            if (!r.activity.mFinished) {
                activity.performStart();
                r.stopped = false;
            }
            if (!r.activity.mFinished) {
                //执行onRestoreInstanceState()
                if (r.isPersistable()) {
                    if (r.state != null || r.persistentState != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                r.persistentState);
                    }
                } else if (r.state != null) {
                    mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                }
            }
            //没有finish()执行onPostCreate()
            if (!r.activity.mFinished) {
                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnPostCreate(activity, r.state,
                            r.persistentState);
                } else {
                    mInstrumentation.callActivityOnPostCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onPostCreate()");
                }
            }
        }
        r.paused = true;
        mActivities.put(r.token, r);
    } catch (SuperNotCalledException e) {
        throw e;
    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to start activity " + component
                + ": " + e.toString(), e);
        }
    }
    return activity;
}复制代码

系不系上面这个方法有点长了,但是很显然是我们开发平时接触很近的方法了
再看看attach()

//主要是给我们activity赋一大堆值
final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
        CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config, String referrer, IVoiceInteractor voiceInteractor,
        Window window, ActivityConfigCallback activityConfigCallback) {
    attachBaseContext(context);

    mFragments.attachHost(null /*parent*/);
    //window创建并赋值
    mWindow = new PhoneWindow(this, window, activityConfigCallback);
    mWindow.setWindowControllerCallback(this);
    mWindow.setCallback(this);
    mWindow.setOnWindowDismissedCallback(this);
    mWindow.getLayoutInflater().setPrivateFactory(this);
    if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
        mWindow.setSoftInputMode(info.softInputMode);
    }
    if (info.uiOptions != 0) {
        mWindow.setUiOptions(info.uiOptions);
    }
    //看见没这就是uiThread
    mUiThread = Thread.currentThread();
    //主线程为ActivityThread
    mMainThread = aThread;
    //原来这货再这赋值的每一个activity都有这个监控类
    mInstrumentation = instr;
    mToken = token;
    mIdent = ident;
    mApplication = application;
    mIntent = intent;
    mReferrer = referrer;
    mComponent = intent.getComponent();
    mActivityInfo = info;
    mTitle = title;
    mParent = parent;
    mEmbeddedID = id;
    mLastNonConfigurationInstances = lastNonConfigurationInstances;
    if (voiceInteractor != null) {
        if (lastNonConfigurationInstances != null) {
            mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
        } else {
            mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                    Looper.myLooper());
        }
    }
    mWindow.setWindowManager(
            (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
            mToken, mComponent.flattenToString(),
            (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    if (mParent != null) {
        mWindow.setContainer(mParent.getWindow());
    }
    mWindowManager = mWindow.getWindowManager();
    mCurrentConfig = config;
    mWindow.setColorMode(info.colorMode);
}复制代码

还要问我activity启动了没有吗,我说没有

scheduleLaunchActivity()、handleLaunchActivity()、performLaunchActivity()
将activity的相关信息淋漓尽致的展现,没事多看看,我还没专研细致的方法呢。

无论你是一个程序猿还是一个程序媛,每天干的事除了coding还是coding,代码不能解决的问题(什么问题自己心里还没点abcd数嘛),探探能帮你解决。最近网上特流行一款交友软件叫探探(据说是yp软件)。作为探探曾经的一名从来只浏览图片但是没有yue过的资深玩家同时又是一位热爱前端的妹子,我决定要仿一下这个app。既然是寄几开发,那还不是寄几说了算,毫无疑问整款APP的主题风格被我改成我最爱的终极少女粉了hhh,下面让我们一起来感受下探探的魅力吧~项目整体效果项目部分功能点解析主页图片左滑右滑对应按钮变化首先我们来聊一下最让我头痛的地方,就是主页面的左右滑动事件并且对应按钮会相应变化,即我左滑一下图片下面的灰色按钮会有相应的动画效果,右滑则对应着图片下面的红色按钮。对于一个刚入小程序坑的妹子来说,没有大神指点不知道要在这里面的逻辑坑还要绕多久才能绕出来。得一高人指点,我才完美滴实现了这个功能。这里写了三个大的盒子放着图片和文字信息,再将他们放到swiper-item里面,用swiper组件实现整个盒子的左右滑动                                          K             ♂21             金牛座             文化/教育                哦盒子下面不是按钮,我是放了两张图片。             先给他们写个滑动的时候触发的动画效果.active {    animation: active 1s ease;//定义一个叫做active的动画} @keyframes active {//补充active动作脚本     0% {        transform: scale(0.8);     }     50% {        transform: scale(1.2);     }     100% {        transform: scale(1.0);     } }在page的data里面定义三个变量,将left,right变量绑定到对应图片中data: {        left: false ,       right: false,        activeIndex: 0 },在swiper绑定事件中具体判断左右滑动事件changeswiper: function(e) {         var index = e.detail.current;//当前所在页面的 index     if(index > this.data.activeIndex) {//左滑事件判断       this.setData({         left: true//若为左滑,left值为true,触发图片动画效果       })     } else if(index  {//每滑动一次,数据发生变化       this.setData({         activeIndex: index,         left:false,         right:false       })     }, 1000);   },从本地上传图片这个呀查一查小程序开发文档就好了,先在要上传图片的地方的src绑定个数据变量放入图片默认地址,就是上传图片之前的添加图片data: {     imgUrl: '../../images/addImg.png'   },通过绑定tap事件将上传的图片地址替换进去uploadImg: function(e) { var that = this; wx.chooseImage({   count: 1, //上传图片数量   sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认者都有   sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认者都有   success: function (res) {// 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片       var tempFilePaths = res.tempFilePaths;       that.setData({           imgUrl: tempFilePaths     })       wx.showToast({//显示上传成功           title: '上传成功',           icon: 'success',           duration: 2000     })   } }),配对成功列表据通过easy-mock获取后台数据block wx:for渲染一个包含多节点的结构块                                                                                                                         {{item.nickname}}                     {{item.message}}                                            获取后台数据wx.request({       url: 'https://www.easy-mock.com/mock/5a23dbf382614c0dc1bebf04/getFriendsList/getFriendsList',       success: (res) => {         // console.log(response);         this.setData({           friendsList: res.data.data.friendsList         })       }     })其它差不多就是切页面了,个人原因用不太习惯weui的官方样式,每个页面都是我自己呕心沥血码出来的,所以大家不喜轻点喷哈,还在努力学习当中~~~项目开发用到的一些工具微信开发者工具、VScode、GithubIconfont阿里巴巴矢量图标库:各种图片logo应有尽有,前端开发必备esay-mock:模拟数据请求,实现无后端编程W3Cschool微信小程序开发教程手册文档:开发小程序要多看看哦小结emmmm目前项目功能还是很简单呀,还有很多功能后面慢慢实现吧~比如利用将上传的图片放到storage中,页面刷新之后图片依然在,slider滑动到某一处在页面上保存当前值,模拟配对成功后弹出提醒页面等等......也希望遇到热爱学习的小伙伴一起交流学习,一起在前端坑里越陷越深hhh项目地址:https://github.com/beautifulg... 求鼓励~求star呀~我的邮箱:804316947@qq.com 这里可以找到我哦作者:略略略
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值