Android——Activity学习(下)

学习资料:

本篇是个挖坑之作,步子跨得太大扯着了。不知天高地厚地开始学习后,发现涉及到很多暂时无法理解的东西。遂,中道崩殂,哈哈:),估计明年这个时候才能补充了

Android——Activity学习(上)学习了Activity的生命周期,启动模式,任务栈,本篇进行学习工作过程

对于用户来说,一个APP能够感知的就是一个Activity,四大组件的其他三位,都是在后台运行的,用户是看不到的,不可感知的。根据上篇的学习,Activity有不同的启动模式,启动方式也可以分为显示Intent隐式Intentfinish()方法可以结束一个组件的运行。

1. 工作过程 <p>

在一个现有Activity_A中,经常会使用一个Intent来开启一个Activity_B

Intent intent = new Intent(Activity_A.this,Activity_B.class);
startActivity(intent);

startActivity()方法可以作为学习的入口点

扫了一眼Activity源码的行数,加上注释7177行,相对于View的23000行来说,小巫见大巫。最近一段时间的学习,感觉最明显的变化便是看源码时的心态。然而也仅仅是心态有了点朝好的趋势发展,阅读代码的能力还是渣

1.1 startActivity() 开启Activity<p>

有两种重载重载方式,startActivity(Intent intent)内部调用了startActivity(Intent intent, @Nullable Bundle options)

@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
            startActivityForResult(intent, -1, options);
    } else {//兼容重载方法
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
    }
}

最终两种形式的startActivity()方法都会调用startActivityForResult()方法

Activity_A并不知道Activity_B的存在,但Activity_A通过使用Intent来启动Activity_B,显式是通过指定类对象,隐式则更加显得强大,通过在AndroidManifest.xml清单文件中使用的action指定的Activity_B的名字来启动。这个设计使Activity耦合性很松散,模块化程度更高,之后维护和升级也更加方便些。

1.2 startActivityForResult()带有返回结果的开启Activity <p>

方法源码:

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,@Nullable Bundle options) {
    if (mParent == null) {//mParent是ActvityGroup,API13后废弃,推荐由Framgment代替
        Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(mToken, mEmbeddedID, requestCode, ar.getResultCode(),
            ar.getResultData());
        }
        if (requestCode >= 0) {//当前Activity返回一个result,无论它发生了什么
            mStartedActivity = true;
        }
        cancelInputsAndStartExitTransition(options);
        // TODO Consider clearing/flushing other event sources and events for child windows.
    } else {//mParent不为null
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {兼容重载方法,以确保重载方法可以使用
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}

上面的代码需要重点关注mParent==null部分内的的逻辑,mParent是一个ActivityGroup,只是在API13之后,被废弃,系统推荐另外一个坑,Frrgment来替代。

mInstrumentationActivity类中的一个成员变量,Instrumentation可以看作是APP和系统之间的监控器,用来监控应用程序和系统间的交互

mMainThread类型是ActivityThread,这里代表的就是程序的主线程。mMainThread.getApplicationThread()获得是一个ActivityThread的内部类ApplicationThread对象。在Android应用程序中,每一个进程就用一个ActivityThread实例对象来表示

本篇博客学习挖的1号坑——ActivityThread,暂时不理解它的工作过程

1.3 Instrumentation的execStartActivity()方法 <p>

源码:

public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode) {  
        IApplicationThread whoThread = (IApplicationThread) contextThread;  
        if (mActivityMonitors != null) {...}  
        try {  
            int result = ActivityManagerNative.getDefault() 
                .startActivity(whoThread,intent,intent.resolveTypeIfNeeded(who.getContentResolver()), null, 0, token, target != null ? target.mEmbeddedID : null, requestCode, false, false);  //才真正开始开启Activity
           checkStartActivityResult(result, intent);//检查异常
        } catch (RemoteException e) {  
        }  
    return null;  
}

整个方法内关键之处在于ActivityManagerNative.getDefault().startActivity(...),真正启动一个Activity便是这行代码。

ActivityManagerNative.getDefault()返回的结果是一个IActivityManager,是一个接口。ActivityManagerNative(AMN)ActivityManagerService(AMS)的父类,AMN继承之Binder并实现了IActivityManager这个Binder接口,因此AMS也是一个Binder,它是IAcitityManager的具体实现。由于ActivityManagerNative.getDefault()结果其实是一个IActivityManager类型的Binder对象,最终的具体实现是AMS,所以Activity的启动也就转移到了AMS中的startActivity()方法。

checkStartActivityResult(result,intent)用于检查启动Activity的结果,当无法正常开启一个Activity时,就会抛出一个异常。例如,一个Activity没有在AnroidManifest.xml中注册时,便会抛出:

Unable to find explict activity class ;
have you declared this activity in your AndroidManifest.xml ?

2号大坑——Binder,任教主推荐了两篇,Android深入浅出之Binder机制Android Bander设计与实现 – 设计篇 ,一脸懵逼,属于有生年看懂系列

接下来看AMSstartActivity()方法

1.4 AMS的startActivity()方法

源码:

卒...

感觉再看下去属于浪费时间,再储备点知识后,再来学习

2. 最后 <p>

尺度太大,学不动,先放弃,这次学习没把握好尺度

写博客以来,第一次中途放弃,实在没有啥效率

2016.10.14 16:28

共勉 :)

    原文作者:英勇青铜5
    原文地址: https://www.jianshu.com/p/60ef60705ade
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞