Android面试题汇总

1.面试题:知道Service吗,它有几种启动方式?
Service是一个专门在后台处理长时间任务的Android组件,它没有UI。它有两种启动方式,startService和bindService。
startService只是启动Service,启动它的组件(如Activity)和Service并没有关联,只有当Service调用stopSelf或者其他组件调用stopService服务才会终止。
如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。
bindService方法启动Service,其他组件可以通过回调获取Service的代理对象和Service交互,而这两方也进行了绑定,当启动方销毁时,Service也会自动进行unBind操作,当发现所有绑定都进行了unBind时才会销毁Service。
如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致 多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。

2.面试题:Service的onCreate回调函数可以做耗时的操作吗?
Service的onCreate是在主线程(ActivityThread)中调用的,耗时操作会阻塞UI

3.面试题:是否知道IntentService,在什么场景下使用IntentService?
IntentService是一个基于Service的一个类,用来处理异步的请求。你可以通过startService(Intent)来提交请求,该Service会在需要的时候创建,当完成所有的任务以后自己关闭,且请求是在工作线程处理的。
使用了IntentService有两个好处,一是不需要自己去new Thread了;二是不需要考虑在什么时候关闭该Service了。

4.面试题:用广播来更新UI界面好吗?
Normal broadcasts无序广播,会异步的发送给所有的Receiver,接收到广播的顺序是不确定的,有可能是同时。
Ordered broadcasts有序广播,广播会先发送给优先级高(android:priority)的Receiver,而且这个Receiver有权决定是继续发送到下一个Receiver或者是直接终止广播。
使用LocalBroadcastManager,发送广播只有自己(本进程)能接收到
广播也是有生命周期的,而且很短,当它的onReceive方法执行完成后,它的生命周期就结束了。这时BroadcastReceiver已经不处于active状态,被系统杀掉的概率极高
如果不是频繁地刷新,使用广播来做也是可以的。但对于较频繁地刷新动作,建议还是不要使用这种方式。

5.面试题:怎么理解Activity的生命周期?
Activity 的可见生命周期发生在 onStart调用与 onStop调用之间。

6.面试题:简单说一下Activity A启动Activity B时,两个Activity生命周期的变化。
当一个 Activity 启动另一个 Activity 时,它们都会发生生命周期转变。第一个 Activity 暂停然后停止(但如果它在后台仍然可见,则不会停止,比如B是半透明的),系统会创建另一个 Activity。 如果这两个Activity 共用保存数据到文件或者数据库,必须要注意,在创建第二个 Activity 前,第一个 Activity 不会完全停止。更确切地说,启动第二个 Activity 的过程与停止第一个 Activity 的过程存在重叠。

7.面试题: 如何判断Activity是否在运行?
if (activity == null || activity.isDestroyed() || activity.isFinishing()) {
return;
}
Handler更新UI的情况,我们需要在操作UI前判断一下此Activity是否已被销毁。

8.面试题:自定义View的状态是如何保存的?
异常退出Activity会自动保存View的状态,用户主动退出不会自动保存
Activity类的onSaveInstanceState默认实现会恢复Activity的状态,默认实现会为布局中的每个View调用相应的 onSaveInstanceState方法,让每个View都能保存自身的信息。
想要保存View的状态,需要在XML布局文件中提供一个唯一的ID(android:id),如果没有设置这个ID的话,View控件的onSaveInstanceState是不会被调用的。

9.面试题:Java的值传递和引用传递问题
基本类型是按值传递的,方法的实参是一个原值的复本。类对象是按对象的引用地址(内存地址)传递地址的值,那么在方法内对这个对象进行修改是会直接反应在原对象上的(或者说这两个引用指向同一内存地址)。不过要注意String这个类型,String的对象是不可修改的,如果真正要达到改变字符串的效果,我们需要使用StringBuilder来替代String。

10.面试题:能讲讲Android的Handler机制吗?
Android应用程序是通过消息来驱动的,系统为每一个应用程序维护一个消息队例(MessageQueue),应用程序的主线程不断地从这个消息队例中获取消息(Looper),然后对这些消息进行处理(Handler),这样就实现了通过消息来驱动应用程序的执行。
使用Handler处理的场景是:使用主线程的Handler和Looper,在子线程中发Message。然后主线程处理 handlerMessage。
使用HandlerThread实现主线程给子线程发消息,让子线程处理任务。

11.面试题:两个Activity之间如何传递参数?
使用Intent的Bundle协带参数,就是我们常用的Intent.putExtra方法。传递一些简单的int,String类型的数据

12.面试题:如何传递自定义的对象呢?
传递实现了Serializable接口的自定义对象或者使用Android的Parcelable
Serializalbe会使用反射,序列化和反序列化过程需要大量I/O操作,Parcelable自已实现封送和解封(marshalled &unmarshalled)操作不需要用反射,数据也存放在Native内存中,效率要快很多。

13.面试题:Parcelable和Parcle这两者之间的关系。
Parcelable接口定义在封送/解封送过程中混合和分解对象的契约。Parcelable接口的底层是Parcel容器对象。Parcel类是一种最快的序列化/反序列化机制,专为Android中的进程间通信而设计。该类提供了一些方法来将成员容纳到容器中,以及从容器展开成员。

14.面试题:在项目中使用AsyncTask会有什么问题吗?
Android3.0之前(1.6之前的版本不再关注)规定线程池的核心线程数为5个(corePoolSize),线程池总大小为128(maximumPoolSize),还有一个缓冲队列(sWorkQueue,缓冲队列可以放10个任务),当我们尝试去添加第139个任务时,程序就会崩溃。当线程池中的数量大于corePoolSize,缓冲队列已满,并且线程池中的数量小于maximumPoolSize,将会创建新的线程来处理被添加的任务。如下图会出现第16个Task比第6-15个Task先执行的情况。
如果AsyncTask被声明为Activity的非静态的内部类,那么AsyncTask会保留一个对创建了AsyncTask的Activity的引用。如果Activity已经被销毁,AsyncTask的后台线程还在执行,它将继续在内存里保留这个引用,导致Activity无法被回收,引起内存泄露。

15.面试题:修改SharedPreferences后两种提交方式有什么区别?
修改SharedPreferences需要获取它的Editor,在对Editor进行put操作后,最后通过commit或者apply提交修改到内存和文件。
commit这种方式很常用,在比较早的SDK版本中就有了,这种提交修改的方式是同步的,会阻塞调用它的线程,并且这个方法会返回boolean值告知保存是否成功(如果不成功,可以做一些补救措施)。
而apply是异步的提交方式,目前Android Studio也会提示大家使用这种方式。

你可能感兴趣的:(Android进阶)