Android开发面试经——3.常见Android进阶笔试题

关注finddreams博客:http://blog.csdn.net/finddreams/article/details/44301359
上一篇文章我们已经了解了Android笔试的一些基础题目,《Android开发面试经——2.常见Android基础笔试题》
但是做为一个有经验的开发者,仅仅知道基础题还是不够的,你的简历上说有两年以上工作经验的话,那面试官肯定会问一些深入性的问题,看你能否回答的出。所以为了找一个更好的工作,我们还需要去了解一下Android进阶的笔试题目:

1.什么是ANR,如何避免?
ANR:Application Not Responding。
在 Android 中,活动管理器和窗口管理器这两个系统服务负责监视应用程序的响应。当出现下列情况时,Android 就会显示 ANR 对话框了:
①.用户对应用程序的操作(如输入事件,按键、触摸屏事件)在5秒内无响应
②. 广播接受器(BroadcastReceiver)在10秒内仍未执行完毕
Android 应用程序完全运行在一个独立的线程中(例如 main)。这就意味着,任何在主 线程中运行的,需要消耗大量时间的操作都会引发 ANR。因为此时,你的应用程序已经没有机会去响应输入事件和意向广播(Intentbroadcast)。
避免方法:Activity 应该在它的关键生命周期方法(如 onCreate()和 onResume())里尽可能少的去做创建操作,
潜在的耗时操作。例如网络或数据库操作,或者高耗时的计算如改变位图尺寸,应该在子线程里(或者异步方式)来完成。
主线程应该为子线程提供一个 Handler,以便完成时能够提交给主线程。

2.Handler机制原理?
andriod 提供了 Handler 和 Looper 来满足线程间的通信。Handler 先进先出原则。
Looper 类用来管理特定线程内对象之间的消息交换 (MessageExchange)。
1)Looper: 一个线程可以产生一个 Looper 对象,由它来管理此线程里的 MessageQueue(消息队列)。
2)Handler: 你可以构造 Handler 对象来与 Looper 沟通,以便 push 新消息到 MessageQueue 里;或者接收 Looper 从 MessageQueue 取出)所送来的消息。
3) Message Queue(消息队列 ): 用来存放线程放入的消息。
4)线程: UI thread 通常就是 main thread, 而 Android 启动程序时会替它建立一个 MessageQueue。

3.请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系。
简单的说,Handler获取当前线程中的 looper对象,looper 用来从存放 Message 的 MessageQueue中取出 Message,再有 Handler 进行 Message 的分发和处理.
Message Queue(消息队列): 用来存放通过 Handler 发布的消息, 通常附属于某一个创建它的线程,可以通过 Looper.myQueue()得到当前线程的消息队列
Handler:可以发布或者处理一个消息或者操作一个 Runnable,通过 Handler发布消息, 消息将只会发送到与它关联的消息队列,然也只能处理该消息队列中的消息
Looper:是 Handler 和消息队列之间通讯桥梁,程序组件首先通过 Handler 把消息传递给 Looper,Looper 把消息放入队列。Looper 也把消息队列里的消息广播给所有的
Handler:Handler 接受到消息后调用 handleMessage进行处理
Message:消息的类型,在 Handler 类中的 handleMessage 方法中得到单个的消息进行处理
在单线程模型下, 为了线程通信问题, Android 设计了一个 Message Queue(消息队列), 线程间可以通过该 Message Queue 并结合 Handler 和 Looper 组件进行信息交换。
下面将对它 们进行分别介绍:
1. Message
Message 消息,理解为线程间交流的信息,处理数据后台线程需要更新 UI ,则发送Message 内含一些数据给 UI 线程。
2. Handler
Handler处理者,是 Message 的主要处理者,负责 Message 的发送,Message 内容的执行处理。后台线程就是通过传进来的 Handler对象引用来 sendMessage(Message)。
而使用 Handler,需要 implement 该类的 handleMessage(Message)方法,它是处理这些
Message 的操作内容,例如 Update UI 。通常需要子类化 Handler 来实现 handleMessage方法。
3. Message Queue
Message Queue 消息队列,用来存放通过 Handler 发布的消息,按照先进先出执行。每个 message queue 都会有一个对应的 Handler。Handler 会向 messagequeue 通过两种方法发送消息:sendMessage 或 post。这两种消息都会插在 message queue 队尾并
按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过 sendMessage发送的是一个 message 对象,会被 Handler 的 handleMessage()函数处理;而通过 post 方法发送的是一个 runnable 对象,则会自己执行。
4. Looper
Looper 是每条线程里的 Message Queue 的管家。Android 没有 Global 的MessageQueue,而 Android 会自动替主线程(UI 线程)建立 Message Queue,但在子线程里并没有建立 Message Queue。 所以调用 Looper.getMainLooper()得到的主线程的 Looper 不为 NULL,但调用 Looper.myLooper()得到当前线程的 Looper 就有可能为 NULL。

4.Android 中线程与线程,进程与进程之间如何通信
1、一个 Android 程序开始运行时,会单独启动一个 Process。
默认情况下,所有这个程序中的 Activity 或者 Service 都会跑在这个 Process。
默认情况下,一个 Android 程序也只有一个 Process,但一个 Process 下却可以有许多个 Thread。
2、一个 Android 程序开始运行时,就有一个主线程 MainThread 被创建。该线程主要负责 UI 界面的显示、更新和控件交互,所以又叫 UI Thread。
一个 Android 程序创建之初,一个 Process 呈现的是单线程模型–即 Main Thread,
所有的任务都在一个线程中运行。所以,Main Thread 所调用的每一个函数,其耗时应该
越短越好。而对于比较费时的工作,应该设法交给子线程去做,以避免阻塞主线程(主线程被阻塞,会导致程序假死 现象) 。
3、Android 单线程模型:Android UI 操作并不是线程安全的并且这些操作必须在 UI 线程中执行。如果在子线程中直接修改 UI,会导致异常。
4.Android 的 的 IPC ( 进程间通信 ) 机制
IPC 是内部进程通信的简称, 是共享 ” 命名管道 ” 的资源。Android 中的 IPC机制是为了让
Activity 和 Service之间可以随时的进行交互,故在 Android 中该机制,只适用于 Activity 和 Service之间的通信,类似于远程方法调用,类似于 C/S 模式的访问。通过定义 AIDL 接口文件来定义 IPC 接口。Servier 端实现 IPC接口,Client 端调用 IPC接口本地代理。

5.Android应用程序框架
技术分享
技术分享

6.View, surfaceView, GLSurfaceView的区别
View 是最基础的,必须在 UI 主线程内更新画面,速度较慢。
SurfaceView 是 view 的子类,类似使用双缓机制,在新的线程中更新画面所以刷新界面速度比 view 快 GLSurfaceView 是 SurfaceView 的子类,opengl 专用的。
区别:SurfaceView是从View基类中派生出来的显示类,直接子类有GLSurfaceView和VideoView,可以看出GL和视频播放以及Camera摄像头一般均使用SurfaceView
SurfaceView和View最本质的区别在于,surfaceView是在一个新起的单独线程中可以重新绘制画面而View必须在UI的主线程中更新画面。
那么在UI的主线程中更新画面 可能会引发问题,比如你更新画面的时间过长,那么你的主UI线程会被你正在画的函数阻塞。那么将无法响应按键,触屏等消息。
当使用surfaceView 由于是在新的线程中更新画面所以不会阻塞你的UI主线程。但这也带来了另外一个问题,就是事件同步。比如你触屏了一下,你需要surfaceView中thread处理,一般就需要有一个event queue的设计来保存touch event,这会稍稍复杂一点,因为涉及到线程同步。

7. AIDL的全称是什么?如何工作?
AIDL 全称 Android Interface Definition Language(Android 接口描述语言)是一种接口描述语言 ; 编译器可以通过 aidl文件生成一段代码, 通过预先定义的接口达到两个进程内
部通信进程跨界对象访问的目的.AIDL 的 IPC 的机制和 COM 或 CORBA 类似 , 是基于接口的, 但它是轻量级的。 它使用代理类在客户端和实现层间传递值 . 如果要使用 AIDL, 需要完成2件事情 :
1. 引入AIDL的相关类 .;
2. 调用 aidl产生的 class.理论上 , 参数可以传递基本数据类型和String, 还有就是Bundle的派生类
当A进程要去调用B进程中的service时,并实现通信,我们通常都是通过AIDL来操作的 。
A工程:
首先我们在net.blogjava.mobile.aidlservice包中创建一个RemoteService.aidl文件,在里面我们自定义一个接口,含有方法get。ADT插件会在gen目录下自动生成一个RemoteService.java文件,该类中含有一个名为RemoteService.stub的内部类,该内部类中含有aidl文件接口的get方法。
说明一:aidl文件的位置不固定,可以任意
然后定义自己的MyService类,在MyService类中自定义一个内部类去继承RemoteService.stub这个内部类,实现get方法。在onBind方法中返回这个内部类的对象,系统会自动将这个对象封装成IBinder对象,传递给他的调用者。
其次需要在AndroidManifest.xml文件中配置MyService类,代码如下:

<!-- 注册服务 -->  
<service android:name=".MyService"> 
   <intent-filter> 
   <!--  指定调用AIDL服务的ID  --> 
       <action android:name="net.blogjava.mobile.aidlservice.RemoteService" /> 
    </intent-filter> 
</service>

为什么要指定调用AIDL服务的ID,就是要告诉外界MyService这个类能够被别的进程访问,只要别的进程知道这个ID,正是有了这个ID,B工程才能找到A工程实现通信。
说明:AIDL并不需要权限
B工程:
首先我们要将A工程中生成的RemoteService.java文件拷贝到B工程中,在bindService方法中绑定aidl服务
绑定AIDL服务就是将RemoteService的ID作为intent的action参数。
说明:如果我们单独将RemoteService.aidl文件放在一个包里,那个在我们将gen目录下的该包拷贝到B工程中。如果我们将RemoteService.aidl文件和我们的其他类存放在一起,那么我们在B工程中就要建立相应的包,以保证RmoteService.java文件的报名正确,我们不能修改RemoteService.java文件
bindService(new Inten(“net.blogjava.mobile.aidlservice.RemoteService”), serviceConnection, Context.BIND_AUTO_CREATE);
ServiceConnection的onServiceConnected(ComponentName name, IBinder service)方法中的service参数就是A工程中MyService类中继承了RemoteService.stub类的内部类的对象。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。