Android常见面试题(一)

总结了一些常见的Android面试题,内容会随着不断学习陆续增加。答案有误地方希望大家可以指正 ,同时希望大家一起补充总结更多常见问题,谢谢^_^

1. 简述Activity的生命周期
2. 请简单说下对广播接收者有哪些了解
3. view如何刷新?简述什么是双缓冲?
4、AIDL的全称是什么?如何工作?能处理哪些类型的数据?
5、java中如何引用本地语言
6、谈谈Android的IPC(进程间通信)机制
7、NDK 是什么
8、如何将SQLite数据库(xxx.db文件)与apk文件一起发布

1.简述Activity的生命周期

1、Activity可见并获得焦点
当Activity启动的时候,首先调用onCreate()、onStart(),onResume()方法,此时Activity对用户来说,是可见的状态

2、Activity可见但没获得焦点
当Activity从可见状态变为被Dialog遮挡的状态的时候,会调用onPause()方法,此时的Activity对用户可见,但是不能获得焦点

3、Activity不可见
当Activity从可见状态变为被其他的Activity完全覆盖或者是点击Home进入后台的时候,会依次调用onPause()//onStop()方法,如果在这个期间,系统内存不足,导致Activity被回收的话,还会调用onDestory()方法

4、Activity可见、没获得焦点状态 –> Activity可见、获得焦点状态
当Activity从被Dialog遮挡的状态恢复的时候,会调用onResume()方法,从而恢复可以点击的状态

5、Activity不可见、没获得焦点状态 –> Activity可见、获得焦点状态
当Activity从被其他Activity遮挡或者是进入后台状态后恢复,若没有被系统回收,会依次调用onRestart()、onStart()、onResume()方法,恢复到可以与用户进行交互的状态

6、Activity不可见状态–> Activity被回收 –> Activity可见、获得焦点状态
当Activity从被其他Activity遮挡或者进入后台,而且被系统回收的时候,此时恢复Activity,相当于重新打开一个Activity,既调用onCreate()、onStart()//onResume()方法,从而恢复到可与用户进行交互的状态(期间可调用onRestoreInstanceState(),进行界面恢复)。

7、Activity可见、获得焦点状态 –> Activity可见、没获得焦点状态 或 不可见状态
在onPause()方法执行后,系统会停止一些消耗 CPU 的操作,因为这个时候程序的优先级降低,很有可能被系统收回,所以我们应该在这个方法里做数据持久化处理。保存的数据可在 onResume() 里读出来,帮用户恢复到之前的状态。

8、Activity结束
在onDestroy()执行后,activity生命周期就结束了,可用 isFinishing()方法来判断。如果此时有 Progress Dialog显示,我们应该在onDestroy()里 cancel 掉,否则线程结束的时候,调用Dialog 的 cancel 方法会抛异常。

2.请简单说下对广播接收者有哪些了解

广播接收者(BroadcastReceiver)用于接收广播Intent,广播Intent的发送是通过调用Context.sendBroadcast()、Context.sendOrderedBroadcast()来实现的。通常一个广播Intent可以被订阅了此Intent的多个广播接收者所接收,这个特性跟JMS中的Topic消息接收者类似。要实现一个广播接收者方法如下:
第一步:继承BroadcastReceiver,并重写onReceive()方法。

public class IncomingSMSReceiver extends BroadcastReceiver {
     @Override public void onReceive(Context context, Intent intent) {
     }
 }

第二步:订阅指定的广播Intent,订阅方法有两种:
第一种:使用代码进行订阅

IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
IncomingSMSReceiver receiver = new IncomingSMSReceiver();
registerReceiver(receiver, filter);

第二种:在AndroidManifest.xml文件中的节点里进行订阅:

  <receiver android:name=".IncomingSMSReceiver">
      <intent-filter>
          <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
     </intent-filter>
 </receiver>

广播类型:

广播分为两种不同的类型:“普通广播(Normal broadcasts)”和“有序广播(Ordered broadcasts)”。普通广播是完全异步的,可以在同一时刻(逻辑上)被所有接收者接收到,消息传递的效率比较高,但缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播;然而有序广播是按照接收者声明的优先级别,被接收者依次接收广播。如:A的级别高于B,B的级别高于C,那么,广播先传给A,再传给B,最后传给C 。优先级别声明在intent-filter元素的android:priority属性中,数越大优先级别越高,取值范围:-1000到1000,优先级别也可以调用IntentFilter对象的setPriority()进行设置 。有序广播的接收者可以终止广播Intent的传播,广播Intent的传播一旦终止,后面的接收者就无法接收到广播。另外,有序广播的接收者可以将数据传递给下一个接收者,如:A得到广播后,可以往它的结果对象中存入数据,当广播传给B时,B可以从A的结果对象集合中得到A存入的数据。

Context.sendBroadcast() 发送的是普通广播,所有订阅者都有机会获得并进行处理。

Context.sendOrderedBroadcast() 发送的是有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者,前面的接收者有权终止广播

BroadcastReceiver.abortBroadcast(),如果广播被前面的接收者终止,后面的接收者就再也无法获取到广播。对于有序广播,前面的接收者可以将数据通过setResultExtras(Bundle)方法存放进结果对象,然后传给下一个接收者,下一个接收者通过代码:Bundle bundle = getResultExtras(true))可以获取上一个接收者存入在结果对象中的数据。

系统收到短信,发出的广播属于有序广播。如果想阻止用户收到短信,可以通过设置优先级,让你们自定义的接收者先获取到广播,然后终止广播,这样用户就接收不到短信了。

广播接收者的响应:
在Android中,每次广播消息到来时都会创建BroadcastReceiver实例并执行onReceive() 方法, onReceive() 方法执行完后,BroadcastReceiver 的实例就会被销毁。当onReceive() 方法在10秒内没有执行完毕,Android会认为该程序无响应。所以在BroadcastReceiver里不能做一些比较耗时的操作,否侧会弹出ANR(Application No Response)的对话框。如果需要完成一项比较耗时的工作,应该通过发送Intent给Service,由Service来完成。这里不能使用子线程来解决,因为BroadcastReceiver的生命周期很短,子线程可能还没有结束BroadcastReceiver就先结束了。BroadcastReceiver一旦结束,此时BroadcastReceiver的所在进程很容易在系统需要内存时被优先杀死,因为它属于空进程(没有任何活动组件的进程)。如果它的宿主进程被杀死,那么正在工作的子线程也会被杀死。所以采用子线程来解决是不可靠的。

public class IncomingSMSReceiver extends BroadcastReceiver {
     @Override 

    public void onReceive(Context context, Intent intent) {
             //发送Intent启动服务,由服务来完成比较耗时的操作
            Intent service = new Intent(context, XxxService.class);
             context.startService(service);
     }
 }

常用广播Intent:

除了短信到来广播Intent,Android还有很多广播Intent,如:开机启动、电池电量变化、时间已经改变等广播Intent。

接收开机启动广播Intent,在AndroidManifest.xml文件中的节点里订阅此Intent:

<receiver android:name=".IncomingSMSReceiver">
     <intent-filter>
          <action android:name="android.intent.action.BOOT_COMPLETED"/>
     </intent-filter>
 </receiver>

并且要进行权限声明:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

接收电池电量变化广播Intent ,在AndroidManifest.xml文件中的节点里订阅此Intent:

<receiver android:name=".IncomingSMSReceiver">
     <intent-filter>
          <action android:name="android.intent.action.BATTERY_CHANGED"/>
     </intent-filter>
 </receiver>

广播接收者的生命周期及使用注意事项

1、广播接收者的生命周期是非常短暂的,在接收到广播的时候创建,onReceive()方法结束之后销毁

2、广播接收者中不要做一些耗时的工作,否则会弹出Application No Response错误对话框,耗时的较长的工作最好放在服务中完成

3、最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉

3.view如何刷新?简述什么是双缓冲?

android中实现view的刷新有两个方法,一个是invalidate(),另一个是postInvalidate(),其中前者是在UI线程自身中使用,而后者在非UI线程中使用。

出现屏幕闪烁是图形编程的一个常见问题。当进行复杂的绘制操作时会导致呈现的图像闪烁或具有其他不可接受的外观。双缓冲的使用解决这些问题。双缓冲使用内存缓冲区来解决由多重绘制操作造成的闪烁问题。当使用双缓冲时,首先在内存缓冲区里完成所有绘制操作,而不是在屏幕上直接进行绘图。当所有绘制操作完成后,把内存缓冲区完成的图像直接复制到屏幕。因为在屏幕上只执行一个图形操作,所以消除了由复杂绘制操作造成的图像闪烁问题。

在android中实现双缓冲,可以使用一个后台画布backcanvas,先把所有绘制操作都在这上面进行。等图画好了,然后在把backcanvas拷贝到
与屏幕关联的canvas上去,如下:

Bitmap bitmapBase = new Bitmap()
Canvas backcanvas = new Canvas(bitmapBase)
backcanvas.draw()...//画图
Canvas c = lockCanvas(null);
c.drawbitmap(bitmapBase);//把已经画好的图像输出到屏幕上
unlock(c)....

4、AIDL的全称是什么?如何工作?能处理哪些类型的数据?

全称是:Android Interface Define Language

在 Android 中, 每个应用程序都可以有自己的进程。在写 UI 应用的时候, 经常要用到
Service。 在不同的进程中, 怎样传递对象呢?显然, Java 中不允许跨进程内存共享。因此传递对象, 只能把对象拆分成操作系统能理解的简单形式, 以达到跨界对象访问的目的。

在J2EE 中,采用 RMI 的方式, 可以通过序列化传递对象。在 Android 中, 则采用 AIDL 的方式。

理论上 AIDL 可以传递 Bundle,实际上做起来却比较麻烦。

AIDL(AndRoid 接口描述语言)是一种借口描述语言; 编译器可以通过 aidl 文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的。 如果需要在一个 Activity 中, 访问另一个 Service 中的某个对象, 需要先将对象转化成 AIDL 可识别的参数(可能是多个参数),然后使用 AIDL 来传递这些参数, 在消息的接收端, 使用这些参数组装成自己需要的对象。

AIDL 的 IPC 的机制和 COM 或 CORBA 类似, 是基于接口的,但它是轻量级的。它使用代理类在客户端和实现层间传递值。如果要使用 AIDL, 需要完成 2 件事情: 1. 引入 AIDL 的相关类; 2.调用 aidl 产生的 class。

AIDL 的创建方法:

AIDL 语法很简单,可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。
由于远程调用的需要, 这些参数和返回值并不是任何类型。下面是些 AIDL 支持的数据类型:
1、 不需要 import 声明的简单 Java 编程语言类型(int,boolean 等);
2、String, CharSequence 不需要特殊声明;
3、 List, Map 和 Parcelables 类型, 这些类型内所包含的数据成员也只能是简单数据类型, String 等其他支持的类型。

5、java中如何引用本地语言

可以用JNI(java native interface java 本地接口)接口

6、谈谈Android的IPC(进程间通信)机制

IPC 是内部进程通信的简称,是共享”命名管道”的资源。Android 中的 IPC 机制是为了
让 Activity 和 Service 之间可以随时的进行交互,故在 Android 中该机制,只适用于 Activity和 Service 之间的通信,类似于远程方法调用,类似于 C/S 模式的访问。通过定义 AIDL 接口文件来定义 IPC 接口。Servier 端实现 IPC 接口,Client 端调用 IPC 接口本地代理。

7、NDK 是什么

NDK 是一些列工具的集合, NDK 提供了一系列的工具,帮助开发者迅速的开发 C/C++的动态库,并能自动将 so 和 java 应用打成 apk 包。

NDK 集成了交叉编译器,并提供了相应的 mk 文件和隔离 cpu、平台等的差异,开发人员只需简单的修改 mk 文件就可以创建出 so。

8、如何将SQLite数据库(xxx.db文件)与apk文件一起发布

可以将xxx.db文件复制到Eclipse Android工程中的res aw目录中。所有在res aw目录中的文件不会被压缩,这样可以直接提取该目录中的文件。可以将xxx.db文件复制到res aw目录中。

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