Android基础题
安卓面试基础题
四大组件
Activity的4大启动模式,与开发中需要注意的问题
Standard 标准模式
说明: Android创建Activity时的默认模式,如果没有为Activity设置启动模式的话,默认为标准模式。每次启动一个Activity都会重新创建一个新的实例入栈,不管这个实例是否存在。
生命周期:如上所示,每次被创建的实例Activity 的生命周期符合典型情况,它的onCreate、onStart、onResume都会被调用。SingleTop 栈顶复用模式
说明:分两种处理情况:需要创建的Activity已经处于栈顶时,此时会直接复用栈顶的Activity,不会再创建新的Activity;若需要创建的Activity不处于栈顶,此时会重新创建一个新的Activity入栈,同Standard模式一样。
生命周期:若情况一中栈顶的Activity被直接复用时,它的onCreate、onStart不会被系统调用,因为它并没有发生改变,但是一个新的方法 onNewIntent会被回调(Activity被正常创建时不会回调此方法)。SingleTask 栈内复用模式
说明:若需要创建的Activity已经处于栈中时,此时不会创建新的Activity,而是将存在栈中的Activity上面的其它Activity全部销毁,使它成为栈顶。
生命周期:同SingleTop 模式中的情况一相同,只会重新回调Activity中的 onNewIntent方法SingleInstance 单实例模式
说明: SingleInstance比较特殊,是全局单例模式,是一种加强的SingleTask模式,它除了具有它所有特性外,还加强了一点:具有此模式的Activity只能单独位于一个任务栈中。这个常用于系统中的应用,例如Launch、锁屏键的应用等等,整个系统中只有一个!所以在我们的应用中一般不会用到,了解即可。
对Activity.runOnUiThread的理解
一般是用来将一个runnable绑定到主线程,在runOnUiThread源码里面会判断当前runnable是否是主线程,如果是直接run,如果不是,通过一个默认的空构造函数handler将runnable post到looper里面,创建构造函数handler,会默认绑定一个主线程的looper对象
子线程能否更新UI?为什么?
子线程是不能直接更新UI的
注意这句话,是不能直接更新,不是不能更新(极端情况下可更新)
绘制过程要保持同步(否则页面不流畅),而我们的主线程负责绘制ui,极端情况就是,在Activity的onResume(含)之前的生命周期中子线程都可以进行更新ui,也就是onCreate,onStart和onResume,此时主线程的绘制还没开始。
Handler机制和原理
首先在UI线程我们创建了一个Handler实例对象,无论是匿名内部类还是自定义类生成的Handler实例对象,我们都需要对handleMessage方法进行重写,在handleMessage方法中我们可以通过参数msg来写接受消息过后UIi线程的逻辑处理,接着我们创建子线程,在子线程中需要更新UI的时候,新建一个Message对象,并且将消息的数据记录在这个消息对象Message的内部,比如arg1,arg2,obj等,然后通过前面的Handler实例对象调用sendMessge方法把这个Message实例对象发送出去,之后这个消息会被存放于MessageQueue中等待被处理,此时MessageQueue的Looper正在不停的把MessageQueue存在的消息取出来,通过回调dispatchMessage方法将消息传递给Handler的handleMessage方法,最终前面提到的消息会被Looper从MessageQueue中取出来传递给handleMessage方法。
为什么在子线程中创建Handler会抛异常?
不能在还没有调用Looper.prepare()
方法的线程中创建Handler。
因为抛出异常的地方,在mLooper 对象为null的时候,会抛出异常。
说明这里的Looper.myLooper(); 的返回值是null。只有调用了Looper.prepare()方法,才会构造一个Looper对象并在 ThreadLocal 存储当前线程的Looper对象。