2017安卓面试题-Android篇

从零开始-Android

当我们的java基础达标之后,我们就可以在地基上添砖加瓦,打造属于自己的android大厦 
下图是我对Android的一点总结 

Android总结

  • Android系统相关
  • Android四大组件
  • Android数据存储
  • Android线程相关
  • Android网络编程
  • Android自定义View
  • Android动画相关
  • Android事件分发
  • Android异常优化
  • Android架构设计
  • Android混合编程
  • Android界面适配

Android系统相关

1.描述下Android的系统架构 
答:android系统从下至上分为Linux内核层,Library库和Runtime运行时库,framework框架层,应用层 
Linux内核层:负责硬件驱动,网络,电源,系统安全,内存管理等功能 
Library库:即c/c++函数库部分,大多数都是开放源代码的函数库 

Runtime运行时库:提供安卓程序运行环境DVM 
framework框架层:封装好可调用的api 
应用层:开发层,java程序员进行开发的层次

2.JVM 和DVM的区别? 
答: 
1.dvm执行的是.dex格式文件 jvm执行的是.class文件 android将.class文件通过dex工具转为.dex文件再与资源文件打包成apk 
2.dvm是基于寄存器的虚拟机,jvm执行是基于虚拟栈的虚拟机 
3.class文件存在很多的冗余信息,dex工具会去除冗余信息,并把所有的.class文件整合到.dex文件中。减少了I/O操作,提高了类的查找速度

Android四大组件

Android四大组件:activity,service,broadcastReceiver,contentprovider

1.介绍下Activity生命周期 四大组件之一,与用户进行交互的界面 
答: 
onCreat()-activity创建时执行,用来做一些初始化的操作绑定视图 
onStart()-activity启动,可能可见但是没有焦点处于后台无法与用户交互 
onResume()-activity正在运行,在前台可见且与能用户进行交互 
onPause()-activity暂停,activity可见但是失去焦点 例如dialog弹出遮挡,当遮挡退去,进入onResume 
onStop()-activity停止,activity不可见进入后台-当重新进入activity中,执行onRestart()返回onStart()中 
onDestroy()-activity销毁,通常在这里进行资源的回收

异常生命周期 : 
1.因为系统内存不足,将应用进程在后台杀死怎么办吗,怎么保存之前的状态? 
这时候我们需要用onSaveInstanceState(Bundle outstate)来保存当前状态, 
下次进入activity在oncreat自动判断bundle是否为空进行状态修复

2.横竖屏切换造成activity的生命周期 
onPause()-onStop()-onDestroy()-onCreat()-onStart()-onResume() 
即会导致activity的销毁和重建 
可以在配置清单里设置activity的configchanges属性android:configchanges=”orientation|keyboardhidden” 
之后横屏会调用onConfigurationChanged方法不会发生销毁

2.介绍下Activity的启动模式 
答:1.默认启动方式(Standrand),每次打开一个activity无论重复都会new且入栈 
2.栈内复用模式(SingleTask),当打开的activity存在于栈内,将其上方的activity都销毁掉,调用onNewIntent方法 
3.栈顶复用模式(SingleTop),如果打开的activity在栈顶,调用onNewIntent方法 
4.单栈单实例(SingleInstance),每次跳转新的activity,会创建一个新栈来存放,且栈中只能有此activity

3.如何退出Activity?如何安全退出已调用多个Activity的Application? 
答:1.activity.finsh(); 
2.back键 
3.抛异常 
4.android.os.Process.killProcess(android.os.Process.myPid());安全 
5.可以开启一个activity任务栈来记录,然后遍历finsh

================================

1.介绍下Service的启动方法 四大组件之一,android中的一种服务机制,默认运行在主线程,在后台间隔一定时间做操作 
答:1.startService() 调用者销毁也不会停止 除非执行stopService 
2.bindService() 调用者销毁就会关闭服务 会调用onUnbind()方法

2.介绍下Service的生命周期 
答:start方法:onCreat-onStartCommand-onDestroy 
bind方法:onCreat-onBind-onUnbind-onDestroy

3.如何保证Service在后台不被kill 
1.用sticku粘性的servcie 
2.在onDestroy中再次启动 
3.提高进程优先级 将其设置为前台状态 
4.用广播保持监听

4.Service与Activity怎么实现通信 
1.通过广播发送消息到activitry 
2.通过与activity进行绑定 
添加一个继承Binder的内部类,并添加相应的逻辑方法 
重写Service的onBind方法,返回我们刚刚定义的那个内部类实例 
Activity中创建一个ServiceConnection的匿名内部类,并且重写里面的onServiceConnected方法和onServiceDisconnected方法,这两个方法分别会在活动与服务成功绑定以及解除绑定的时候调用,在onServiceConnected方法中,我们可以得到一个刚才那个service的binder对象,通过对这个binder对象进行向下转型,得到我们那个自定义的Binder实例,有了这个实例,做可以调用这个实例里面的具体方法进行需要的操作了

5.IntentService与Service的区别? 
IntentService是Service的子类,是一个异步的,会自动停止的服务,很好解决了传统的Service中处理完耗时操作忘记停止并销毁Service的问题

6.介绍下AIDL? 
Android Interface Definition Language安卓接口定义语言 

用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码 
如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数。 AIDL IPC机制是面向接口的但是更加轻量级。它是使用代理模式在客户端和实现端传递数据。

================================

1.介绍下BroadcastReceiver 
BroadcastReceiver广播接收者,接收系统或其他应用的广播,内部的实现为Binder机制 
广播分为两种:有序广播(按照接收者优先级发送,在之中依次传播,可以得到上个接收者保存的处理的结果,每个接收者有权拦截广播),无序广播(任何广播接收者都可以收到 效率高)

2.广播接收者的注册方式 
1.动态注册:在代码中注册,传入接收者和IntentFilter,生命周期与引用者相关 
2.静态注册:在配置清单中注册,即使程序关闭也能接收到广播

3.粘性广播有什么作用? 
粘性广播解决动态注册的接收者接收广播的问题 
//例如接收者是通过程序中的某个按钮动态注册的

================================

1.什么是ContentProvider? 
内容提供者,安卓四大组件之一,如果想将自身的数据共享给其他应用就用这个实现 
是应用程序之间共享数据的接口

2.为什么要用 ContentProvider? 它和sql 的实现上有什么差别? 
ContentProvider 屏蔽了数据存储的细节,内部实现对用户完全透明,用户只 需要关心操作数据的 uri 就可以了,ContentProvider 可以实现不同app之间共享。 
Sql 也有增删改查的方法,但是 sql 只能查询本应用下的数据库。而 ContentProvider 还可以去增删改查本地文件. xml 文件的读取等

3.说说ContentProvider 、 ContentResolver 、 ContentObserver 之间的关系 
a. ContentProvider 内容提供者,用于对外提供数据 
b. ContentResolver.notifyChange(uri)发出消息 
c. ContentResolver 内容解析者,用于获取内容提供者提供的数据 
d. ContentObserver 内容监听器,可以监听数据的改变状态 
e. ContentResolver.registerContentObserver()监听消息。


Android数据存储

1.Android数据存储有哪几种方式? 
1.SharedPreference偏好设置 
2.SQLite数据库 
3.IO存储 
4.ContentProvider共享数据 
5.网络存储

2.SQLite的基本操作和SQLite语句? 
首先需要创建库和表,并且需要继承SQLiteOpenHelper类,然后通过这个类得到数据库对象,然后在这个表里面实现增删改查的方法,可以用Android官方封装好的方法进行,也可以调用SQL语句进行操作。调用SQLiteDatabase中的execSQL方法操作SQL语句。

SQLite常用语句 
http://www.wtoutiao.com/p/2369hNQ.html

3.XML和JSON的优缺点?

XML 扩展标记性语言,格式统一,容易交互共享方便 
文件庞大,数据复杂,解析繁琐

JSON 数据格式简单易于读写 易于解析 支持多种语言易于服务端开发维护 
没有XML的通用性,使用广泛

4.XML和JSON的解析? 
XML解析: 
1.DOM可以以一种独立于平台和语言的方式访问和修改一个文档的内容和结构。Dom技术使得用户页面可以动态地变化,如可以动态地显示或隐藏一个元素,改变它们的属性,增加一个元素等,Dom技术使得页面的交互性大大地增强 
缺点是DOM解析XML文件时,会将XML文件的所有内容以文档树方式存放在内存中

2.SAX 用于处理XML事件驱动的“推”模型 解析速度快并且占用内存少的 
缺点是它不会记录标签的关系,而要让你的应用程序自己处理,这样就增加了你程序的负担

3.PULL和SAX解析很相似,不一样的地方是pull读取xml文件后触发相应的事件调用方法返回的是数字还有pull可以在程序中控制想解析到哪里就可以停止解析

Json解析: 
安卓提供的api JsonObject 和JsonArray


Android线程相关

1.介绍下Handler消息机制? 
消息机制的成员有: 
Message:消息的载体 
MessageQueue:消息队列,批量存放消息 

Looper:轮循者,通过轮循MessageQueue取出Message将其交由Handler处理 
Handler:消息的处理者和发送者

当我们需要发送消息让其运行在主线程中时,通过handler.sendMessage,将消息发送到消息队列中等待Looper轮循取出,当取出到这个消息,Looper会将这个消息传递到Handler所在线程进行具体的处理

通过构建一个消息队列,把所有的Message进行统一的管理,当Message不用了,并不作为垃圾回收,而是放入消息队列中,供下次handler创建消息时候使用,提高了消息对象的复用,减少系统垃圾回收的次数

每一个线程都有一个对应的Looper,每个Looper在初始化时会创建对应的消息队列

2.谈谈对HandlerThread的理解 
HandlerThread是Thread的一个子类,他天生自带Looper和消息队列 
可以帮助非UI线程使用消息队列,可以通过消息重复使用当前线程工作

3.安卓进程优先级 
1.前台进程:正在与用户交互 
2.可见进程:不能交互但可见 
3.服务进程:service执行着重要的任务 
4.后台进程:对用户体验无影响的进程,例如onstop的activity 
5.空进程:未运行任何组件的进程

4.AsyncTask异步任务

1.AsynTask为什么要设计为只能够一次任务? 
线程安全问题,多子线程同时运行,会产生状态不一致的问题

2.AsyncTask造成的内存泄露的问题怎么解决? 
起因:非静态的自定义AsyncTask内部类,如果doInBackground任务没执行完,activity就被销毁了,这样

asyncTask并不会被销毁,会等到任务执行完,这个时候asyncTask持有activity的引用导致activity无法回收造成内存泄露 
解决: 
1.同步生命周期 
2.使用弱引用方式,让异步任务持有activity的弱引用

3.若Activity异常销毁导致重新创建,如何更新AsyncTask的引用? 
例如旋转屏幕,会回调Activity.onRetainNonConfigurationInstance()重新传递一个新的对象给AsyncTask,完成引用的更新

5.只能在UI线程里面更新界面吗? 
不一定,之所以子线程不能更新界面,是因为Android在线程的方法里面ViewRootImpl类中采用checkThread进行判断是否是主线程,这个类是在onResume里面才生成的,因此,如果这个时候子线程在onCreate方法里面生成更新UI,而且没有做阻塞,就是耗时多的操作,还是可以更新UI的。


Android网络编程

1.GET和POST的区别 
Get通常用于向服务器获取资源,GET提交请求是将参数放入URL中,可以从URL中看出参数 上限为1024字节 
Post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程,无上限,安全性更高

2.图片三级缓存的实现 
图片的三级缓存分为:内存缓存,文件缓存,网络缓存 
内存缓存:通过LruCache限制缓存大小,并以url为键,bitmap为值存入LruCache中 
文件缓存:将文件或bitmap都可以通过bitmap的api进行互相转化 
网络缓存:从网络中得到输入流得到bitmap对象分别存储到文件和内存 

整合实现:传入url,先从内存中取若无,从文件中取,若无再从网络中取

3.LruCache介绍 
LruCache 底层是LinkedHashMap 
任意时刻,当一个值被访问时,它就会被移动到队列的开始位置,所以这也是为什么要用LinkedHashMap的原因,因为要频繁的做移动操作,为了提高性能,所以要用LinkedHashMap。当cache满了时,此时再向cache里面添加一个值,那么,在队列最后的值就会从队列里面移除,这个值就有可能被GC回收掉。

4.Volley源码实现 
主线程中,请求按照优先级顺序加入到缓存线程的缓存队列中,如果找到缓存,就从缓存中取得相应数据并解析,在主线程回调处理。如果没有 
找到就进入网络线程的网络请求队列,进行Http请求,获取相应数据并解析并写入缓存,在主线程回调处理


Android自定义View

View的绘制流程 
自定义View绘制流程

这里写图片描述

measure()方法,layout(),draw()三个方法主要存放了一些标识符,来判断每个View是否需要再重新测量,布局或者绘制,主要的绘制过程还是在onMeasure,onLayout,onDraw这个三个方法中

1.onMesarue() 为整个View树计算实际的大小,即设置实际的高(对应属性:mMeasuredHeight)和宽(对应属性: mMeasureWidth),每个View的控件的实际宽高都是由父视图和本身视图决定的。

2.onLayout() 为将整个根据子视图的大小以及布局参数将View树放到合适的位置上。

3.onDraw() 开始绘制图像,绘制的流程如下

首先绘制该View的背景 
调用onDraw()方法绘制视图本身 (每个View都需要重载该方法,ViewGroup不需要实现该方法) 
如果该View是ViewGroup,调用dispatchDraw ()方法绘制子视图


Android动画相关

1.Android中的动画有哪些,区别是什么 
逐帧动画(Drawable Animation): 加载一系列Drawable资源来创建动画,简单来说就是播放一系列的图片来实现动画效果,可以自定义每张图片的持续时间

补间动画(Tween Animation): Tween可以对View对象实现一系列简单的动画效果,比如位移,缩放,旋转,透明度等等。但是它并不会改变View属性的值,只是改变了View的绘制的位置,比如,一个按钮在动画过后,不在原来的位置,但是触发点击事件的仍然是原来的坐标。

属性动画(Property Animation): 动画的对象除了传统的View对象,还可以是Object对象,动画结束后,Object对象的属性值被实实在在的改变了


Android事件分发

这里写图片描述

1.介绍触摸事件的分发机制 
(1) 事件从Activity.dispatchTouchEvent()开始传递,只要没有被停止或拦截,从最上层的View(ViewGroup)开始一直往下(子View)传递。子View可以通过onTouchEvent()对事件进行处理。

(2) 事件由父View(ViewGroup)传递给子View,ViewGroup可以通过onInterceptTouchEvent()对事件做拦截,停止其往下传递。

(3) 如果事件从上往下传递过程中一直没有被停止,且最底层子View没有消费事件,事件会反向往上传递,这时父View(ViewGroup)可以进行消费,如果还是没有被消费的话,最后会到Activity的onTouchEvent()函数。

(4) 如果View没有对ACTION_DOWN进行消费,之后的其他事件不会传递过来。

(5) OnTouchListener优先于onTouchEvent()对事件进行消费。

上面的消费即表示相应函数返回值为true。

2.View中 setOnTouchListener的onTouch,onTouchEvent,onClick的执行顺序

追溯到View的dispatchTouchEvent源码查看,有这么一段代码

public boolean dispatchTouchEvent(MotionEvent event) { 
if (!onFilterTouchEventForSecurity(event)) { 
return false; 
}

    if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&  
            mOnTouchListener.onTouch(this, event)) {  
        return true;  
    }  
    return onTouchEvent(event);  
}

当以下三个条件任意一个不成立时,

mOnTouchListener不为null 
view是enable的状态 
mOnTouchListener.onTouch(this, event)返回true, 
函数会执行到onTouchEvent。在这里我们可以看到,首先执行的是mOnTouchListener.onTouch的方法,然后

是onTouchEvent方法

继续追溯源码,到onTouchEvent()观察,发现在处理ACTION_UP事件里有这么一段代码

if (!post(mPerformClick)) { 
performClick(); 

此时可知,onClick方法也在最后得到了执行

所以三者的顺序是:

setOnTouchListener() 的onTouch 
onTouchEvent() 
onClick()


Android异常优化

1.介绍下OOM及其优化方法

OOM-out of Memory内存溢出 
起因:应用申请的内存超过app最大限制申请内存,就会弹出异常对话框 
出现场景:1.大图片处理不当 
2.静态变量持有大数据的引用 
3.资源对象未关闭 
4.非静态内部类持有外部类的引用,导致外部类无法被回收,导致内存泄露 
5.Handler内存泄露

优化方法:1.对bitmap进行压缩,进行复用,减小bitmap内存占用 
2.尽量不使用大数据当做静态变量 

3.资源对象在合适的时机要及时销毁 
4.使用静态内部类若需要引用可以在这个内部类中持有外部类对象的弱引用

2.介绍下ANR及其优化方法

ANR-Application Not Responcing 应用未响应 
起因:应用卡顿长时间卡顿,无法与用户交互就会报错弹出异常对话框 
activity5S内未能响应用户的操作,broadcastReceiver的onreceive方法超过10S,Service执行时间超过20S 
一般是在这些组件所在的主线程中执行了耗时操作,IO操作,错误的线程操作等

优化方法:基本都是将耗时操作和IO操作放在子线程中执行 
1.Handler消息机制 
2.AsyncTask异步任务 
3.降低子线程的优先级 
4.使用IntentService

3.介绍下内存泄露及其优化方法 
内存泄露:不再需要使用的对象被持有着引用没有被及时回收,占用着资源,产生内存泄露

出现场景:1.集合类泄漏 
2.单例造成的内存泄漏(context生命周期不同步) 
3.非静态内部类创建静态实例造成的内存泄漏(持有外部类的引用) 
4.Handler 造成的内存泄漏(耗时太长,消息处理的太久而activity关闭) 
5.资源未关闭造成的内存泄漏

优化方法: 
1保持对对象生命周期的敏感,特别注意单例、静态对象、全局性集合等的生命周期。 
4.Handler 的持有的引用对象最好使用弱引用,资源释放时也可以清空 Handler 里面的消息。比如在 Activity 

onStop 或者 onDestroy 的时候,取消掉该 Handler 对象的 Message和 Runnable.


Android架构设计

1.软件设计的五个原则

1.单一职责原则:一个类只干一个事情 一个方法里只有一个事务 
2.依赖倒置原则:给类设置接口或抽象类 不再依赖调用具体的类 针对接口或抽象类编程 有很大灵活性 
3.开闭原则:模块,类,功能应该在不修改现有代码的基础上,引入新功能 
4.里式替换原则:子类可以扩展父类的功能,但不能改变父类原有的功能 
5.接口隔离原则:每个接口都是针对某一业务配置的 即给不同的人制定不同的套餐


Android混合编程

1.JNI,NDK介绍 
JNI:java native interface java原生接口,提供了api让java语言与其他语言写的代码交互(c,c++)

NDK:native development kit 原生开发包 ,使用JNI机制的开发包

2.NDK使用步骤 
1.安装NDK工具 
2.写native方法 
3.生成.h头文件,使用C/C++实现本地方法 
4.编译动态生成.so库 
5.使用Sysytem.load方法把so库加载进来,就可以调用native方法了

3.Native与JS的交互

Android界面适配

1.dp与px的换算规则 
以160dpi(密度)为基准,1dp=1px,若密度是320dpi,则1dp=2px,以此类推。

2.屏幕适配方式都有哪些 
1.图片适配:进行图片的切图,为各种分辨率的手机提供不同分辨率的图片,drawable-ldpi drawable-mdpi drawable-hdpi drawable-xhdpi drawable-xxhdpi 
2.权重适配,利用LinearLayout的weight来配置布局 
3.百分比适配,Android5.0之后的提供的,还不是很完善 
4.尺寸适配 
5.代码适配:在代码中进行控件的适配




源码分析相关面试题

Activity相关面试题

与XMPP相关面试题

与性能优化相关面试题

与登录相关面试题

与开发相关面试题

与人事相关面试题

在service里面启动activity,但是会发现报如下异常:

必须添加FLAG_ACTIVITY_NEW_TASK这个标记就可以了,那么为什么在activity里面不需要呢?接下来通过从源码角度带大家分析。

启动activity有两种形式

1)直接调用Context类的startActivity方法;这种方式启动的Activity没有Activity栈,因此不能以standard方式启动,必须加上FLAG_ACTIVITY_NEW_TASK这个Flag,服务就是通过Context调用。

2)调用被Activity类重载过的startActivity方法,通常在我们的Activity中直接调用这个方法就是这种形式;

Context.startActivity源码分析

我们查看Context类的startActivity方法,发现这竟然是一个抽象类;查看Context的类继承关系图如下: 

我们看到诸如Activity,Service等并没有直接继承Context,Activity继承了ContextThemeWrapper,Service而是继承了ContextWrapper;

现在从源码分析ContextWrapper的实现:
@Override
public void startActivity(Intent intent) {
        mBase.startActivity(intent);
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

这个mBase是什么呢?这里我先直接告诉你,它的真正实现是ContextImpl类;至于为什么,有一条思路:在任意mBase打一个断点就能看到实现。

Context.startActivity最终使用了ContextImpl里面的方法,代码如下:

 @Override
    public void startActivity(Intent intent, Bundle options) {
        warnIfCallingFromSystemProcess();
        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
            throw new AndroidRuntimeException(
                    "Calling startActivity() from outside of an Activity "
                    + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                    + " Is this really what you want?");
        }
        mMainThread.getInstrumentation().execStartActivity(
                getOuterContext(), mMainThread.getApplicationThread(), null,
                (Activity) null, intent, -1, options);
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
源码分析:

1)大家看看抛出来的异常是不是还是熟悉的味道。

2)通过判断可知当前的intent.getFlags是否带有FLAG_ACTIVITY_NEW_TASK这个标记,如果没有抛出异常,因为源码使用了&运算符,只有两个位都是1,结果才是1,所以可知service没有带FLAG_ACTIVITY_NEW_TASK标记,才抛出异常。

3)真正的startActivity使用了Instrumentation类的execStartActivity方法;继续跟踪:

 public ActivityResult execStartActivity(
     Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {
      ......
try {
     ......
     int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                   intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
源码分析:

1)到这里我们发现真正调用的是ActivityManagerNative的startActivity方法;

Activity.startActivity源码分析

@Override
public void startActivity(Intent intent) {
        this.startActivity(intent, null);
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
源码可知:

1)调用当前类的startActivity方法,代码如下:

@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);
        }
    }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
源码可知

1)调用了startActivityForResult

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
   ......
   Instrumentation.ActivityResult ar =
          mInstrumentation.execStartActivity(
          this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
    ......                 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
源码可知

1)可以看到,其实通过Activity和ContextImpl类启动Activity并无本质不同,他们都通过Instrumentation这个辅助类调用到了ActivityManagerNative的方法。

2)只是Activity不会去检查标记,所以并不会抛出异常。

至此源码分析完毕。


  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值