Android面试题目

1.android dvm 的进程和Linux的进程,应用程序的进程是否为同一个概念:

答:dvmdalivk虚拟机。每一个android应用程序都在自己的进程中运行,都拥有一个dalivk虚拟机实例。而每一个dvm都是在linux的一个进程。所以说可以认为是同一个概念。

 

2.android的动画有哪几种?他们的特点和区别是什么?

答:两种,一种是tween动画,一种是frame动画。tween动画,这种实现方式可以使视图组件移动,放大或缩小以及产生透明度的变化。frame动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。

 

3.handler进制的原理:

答:android提供了handlerlooper来满足线程间的通信。Handler先进先出原则。looper用来管理特定线程内对象之间的消息交换(message Exchange.

    1)looper:一个线程可以产生一个looper对象,由它来管理此线程里的message queue(消息队列)

    2)handler:你可以构造一个handler对象来与looper沟通,以便push新消息到messagequeue里;或者接收looper(从messagequeue里取出)所送来的消息。

    3)messagequeue:用来存放线程放入的消息。

    4)线程:UI thread 通常就是main thread,android启动程序时会为它建立一个message queue.

 

4.android view的刷新

答:Android中对View的更新有很多种方式,使用时要区分不同的应用场合。我感觉最要紧的是分清:多线程和双缓冲的使用情况。
    1).不使用多线程和双缓冲
   这种情况最简单了,一般只是希望在View发生改变时对UI进行重绘。你只需在Activity中显式地调用View对象中的invalidate()方法即可。系统会自动调用 ViewonDraw()方法。
    2).使用多线程和不使用双缓冲
    这种情况需要开启新的线程,新开的线程就不好访问View对象了。强行访问的话会报:android.view.ViewRoot$CalledFromWrongThreadExceptionOnly the originalthread that created a view hierarchy can touch its views.
    这时候你需要创建一个继承了android.os.Handler的子类,并重写handleMessage(Messagemsg)方法。android.os.Handler是能发送和处理消息的,你需要在Activity中发出更新UI的消息,然后你的Handler(可以使用匿名内部类)中处理消息(因为匿名内部类可以访问父类变量,你可以直接调用View对象中的invalidate()方法 )。也就是说:在新线程创建并发送一个Message,然后主线程中捕获、处理该消息。
    3).使用多线程和双缓冲
    AndroidSurfaceViewView的子类,她同时也实现了双缓冲。你可以定义一个她的子类并实现SurfaceHolder.Callback接口。由于实现SurfaceHolder.Callback接口,新线程就不需要android.os.Handler帮忙了。SurfaceHolderlockCanvas()方法可以锁定画布,绘制玩新的图像后调用unlockCanvasAndPost(canvas)解锁(显示),还是比较方便得。

 

Android中实现view的更新有两组方法,一组是invalidate,另一组是postInvalidate,其中前者是在UI线程自身中使用,而后者在非UI线程中使用。 

 

Android中的SurfaceView类就是双缓冲机制。因此,开发游戏时尽量使用SurfaceView而不要使用View,这样的话效率较高,而且SurfaceView的功能也更加完善。为了更容易的了解双缓冲技术,下面介绍用View实现双缓冲的方法。

先概述一下,双缓冲的核心技术就是先通过setBitmap方法将要绘制的所有的图形会知道一个Bitmap上,然后再来调用drawBitmap方法绘制出这个Bitmap,显示在屏幕上。

 

一、双缓冲作用

     双缓冲甚至是多缓冲,在许多情况下都很有用。一般需要使用双缓冲区的地方都是由于“生产者”和“消费者”供需不一致所造成的。这样的情况在很多地方后可能会发生,使用多缓冲可以很好的解决。我举几个常见的例子:

    例 1. 在网络传输过程中数据的接收,有时可能数据来的太快来不及接收导致数据丢失。这是由于“发送者”和“接收者”速度不一致所致,在他们之间安排一个或多个缓冲区来存放来不及接收的数据,让速度较慢的“接收者”可以慢慢地取完数据不至于丢失。

    例2. 再如,计算机中的三级缓存结构:外存(硬盘)、内存、高速缓存(介于CPU和内存之间,可能由多级)。从左到右他们的存储容量不断减小,但速度不断提升,当然价格也是越来越贵。作为“生产者”的 CPU 处理速度很快,而内存存取速度相对CPU较慢,如果直接在内存中存取数据,他们的速度不一致会导致 CPU  能力下降。因此在他们之间又增加的高速缓存来作为缓冲区平衡二者速度上的差异。

     例3. 在图形图像显示过程中,计算机从显示缓冲区取数据然后显示,很多图形的操作都很复杂需要大量的计算,很难访问一次显示缓冲区就能写入待显示的完整图形数据,通常需要多次访问显示缓冲区,每次访问时写入最新计算的图形数据。而这样造成的后果是一个需要复杂计算的图形,你看到的效果可能是一部分一部分地显示出来的,造成很大的闪烁不连贯。而使用双缓冲,可以使你先将计算的中间结果存放在另一个缓冲区中,但全部的计算结束,该缓冲区已经存储了完整的图形之后,再将该缓冲区的图形数据一次性复制到显示缓冲区。

     例1 中使用双缓冲是为了防止数据丢失,例2 中使用双缓冲是为了提高 CPU 的处理效率,而例3使用双缓冲是为了防止显示图形时的闪烁延迟等不良体验。

 

5.说说mvc模式的原理,它在android中的运用:

6.Activity的生命周期:

 

7.Activity变成一个窗口:

答:Activity属性设定:有时候会做个应用程序是漂浮在手机主界面的。这个只需要设置下Activity的主题theme,即在Manifest.xml定义Activity的地方加一句:

android :theme="@android:style/Theme.Dialog"
如果是作半透明的效果:

android:theme="@android:style/Theme.Translucent"

 

8.Android中常用的五种布局:

答:LinearLayout线性布局;AbsoluteLayout绝对布局;TableLayout表格布局;RelativeLayout相对布局;FrameLayout帧布局;

 

9.Android的五种数据存储方式:

答:sharedPreferences;文件;SQLitecontentProvider;网络

 

10.请解释下在单线程模型中MessageHandlerMessage QueueLooper之间的关系:

答:Handler获取当前线程中的looper对象,looper用来从存有MessageMessage Queue里取出message,再由Handler进行message的分发和处理。

 

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

答:AIDL(AndroidInterface Definition Language)android接口描述语言

12.系统上安装了多种浏览器,能否指定某浏览器访问指定页面?请说明原由:

答:通过直接发送Uri把参数带过去,或者通过manifest里的intentfilter里的data属性。代码如下:
Intent intent = new Intent();

Intent.setAction(“android.intent.action.View”);

Uri uriBrowsers = Uri.parse(“http://www.sina.com.cn”);

Intent.setData(uriBrowsers);

//包名、要打开的activity
intent.setClassName(“com.android.browser”,”com.android.browser.BrowserActivity”);

startActivity(intent);

 

13.什么是ANR,如何避免?

答:ANR的定义:

android上,如果你的应用程序有一段时间响应不灵敏,系统会向用户提示应用程序无响应ANRApplication Not Responding)对话框。因此,在程序里对响应性能的设计很重要,这样,系统不会显示ANR给用户。


14.什么情况会导致Force Close?如何避免?能否捕获导致其的异常?

答:如空指针等可以导致ForceClose;可以看Logcat,然后找到对应的程序代码来解决错误。

 

15.横竖屏切换时候的activity的生命周期:

16.如何将SQLite数据库(.db文件)apk文件一起发布?

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

17.如何将打开res aw目录中的数据库文件?

18.android 中有哪几种解析xml的类?官方推荐哪种?以及它们的原理和区别:

19.DDMSTraceView的区别?

答:DDMS是一个程序执行查看器,在里面可以看见线程和堆栈等信息,TraceView是程序性能分析器

20.谈谈AndroidIPC机制:

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

21.NDK是什么:

答:NDK是一系列工具的集合

    NDK提供了一系列的工具,帮助开发者迅速的开发C/C++的动态库,并能自动将sojava应用打成apk

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

22.描述一下android的系统架构:

答:android系统架构分从下往上为Linux内核层、运行库、应用程序框架层和应用程序层。

    Linux内核层:负责硬件的驱动程序、网络、电源、系统安全以及内存管理等功能。

运行库和androidruntion:运行库:即c/c++函数库部分,大多数都是开放源代码的函数库,例如webkit,该函数库负责android网页浏览器的运行;例如标准的c函数库libcopensslsqlite等,当然也包括支持游戏开发的2dsgl3dopengles,在多媒体方面有mediaframework框架来支持各种影音和图形文件的播放与显示,mpeg4h.264mp3aacamrjpgpng等众多的多媒体文件格式。Androidruntion负责解释和执行生成的dalvik格式的字节码

应用软件架构:java应用程序开发人员主要是使用该层封装好的api进行快速开发的。

应用程序层:该层是java的应用程序层,android内置的googlemapsemailIM、浏览器等,都处于该层,java开发人员工发的程序也处于该层,而且和内置的应用程序具有平等的地位,可以调用内置的应用程序,也可以替换内置的应用程序

 

23.Activity 与 Task的启动模式有哪些,它们含义具体是什么?

答:在一个activity中,有多次调用startActivity来启动另一个activity,要想只生成一个activity实例,可以设置启动模式。

    一个activity有四种启动模式:standed,signleTop,singleTask,singleInstance

Activity启动模式设置:
        
Activity的四种启动模式:
. standard
        模式启动模式,每次激活Activity时都会创建Activity,并放入任务栈中。
. singleTop
        如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,否者就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例)
. singleTask
        如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的onNewIntent())。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈。如果栈中不存在该实例,将会创建新的实例放入栈中。 
. singleInstance
        在一个新栈中创建该Activity实例,并让多个应用共享改栈中的该Activity实例。一旦改模式的Activity的实例存在于某个栈中,任何应用再激活改Activity时都会重用该栈中的实例,其效果相当于多个应用程序共享一个应用,不管谁激活该Activity都会进入同一个应用中。

    Standed:标准模式,一调用startActivity()方法就会产生一个新的实例。

    SingleTop:如果已经有一个实例位于activity栈顶,就不产生新的实例,而只是调用activity中的newInstance()方法。如果不位于栈顶,会产生一个新的实例。

    singleTask:会在一个新的task中产生这个实例,以后每次调用都会使用这个,不会去产生新的实例了。

    SingleInstance:这个和singleTask基本一样,只有一个区别:在这个模式下的activity实例所处的task中,只能有这个activity实例,不能有其他实例

 

24.Application类的作用:

答:API里的第一句是:

Base class for those who need to maintain global application state 

如果想在整个应用中使用全局变量,在java中一般是使用静态变量,public类型;而在android中如果使用这样的全局变量就不符合Android的框架架构,但是可以使用一种更优雅的方式就是使用Application context 
     首先需要重写Application,主要重写里面的onCreate方法,就是创建的时候,初始化变量的值。然后在整个应用中的各个文件中就可以对该变量进行操作了。 
     启动Application时,系统会创建一个PID,即进程ID,所有的Activity就会在此进程上运行。那么我们在Application创建的时候初始化全局变量,同一个应用的所有Activity都可以取到这些全局变量的值,换句话说,我们在某一个Activity中改变了这些全局变量的值,那么在同一个应用的其他Activity中值就会改变

 

25.说明onSaveInstanceState() 和 onRestoreInstanceState()在什么时候被调用:

答:Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,它们不同于 onCreate()onPause()等生命周期方法,它们并不一定会被触发。当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity时,onSaveInstanceState()才会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。因为在这种情况下,用户的行为决定了不需要保存Activity的状态。通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。

另外,当屏幕的方向发生了改变, Activity会被摧毁并且被重新创建,如果你想在Activity被摧毁前缓存一些数据,并且在Activity被重新创建后恢复缓存的数据。可以重写Activity的 onSaveInstanceState() 和 onRestoreInstanceState()方法。

26.androidservice的生命周期?哪个方法可以多次被调用:

 

27.androidbroadcast的生命周期:

答:1)Broadcast receiver生命周期中仅有一个回调方法: 
void onReceive(Context curContext, Intent broadcastMsg) 
当接收器接收到一条broadcast消息,Android就会调用onReceiver(),并传递给它一个Intent对象,这个对象携带着那条broadcast消息。我们认为仅当执行这个方式时,Broadcast receiver是活动的;这个方法返回时,它就终止了。这就是Broadcast receiver的生命周期。 


2)由于Broadcast receiver的生命周期很短,一个带有活动的Broadcast receiver的进程是受保护的,以避免被干掉;但是别忘了有一点,Android会在任意时刻干掉那些携带不再活动的组件的进程,所以很可能会造成这个问题。 


3)解决上述问题的方案采用一个Service来完成这项工作,Android会认为那个进程中(Service所在的进程)仍然有在活动的组件。 

28.android viewsurfaceviewglsurfaceview的区别:

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

所以基于以上,根据游戏特点,一般分成两类。 

1)被动更新画面的。比如棋类,这种用view就好了。因为画面的更新是依赖于 onTouch 来更新,可以直接使用 invalidate。 因为这种情况下,这一次Touch和下一次的Touch需要的时间比较长些,不会产生影响。 

2)主动更新。比如一个人在一直跑动。这就需要一个单独的thread不停的重绘人的状态,避免阻塞main UI thread。所以显然view不合适,需要surfaceView来控制。

 

 

29dp,px,sp区别及使用场景

Px:即像素,1px代表屏幕上一个物理的像素点;px单位不被建议使用,因为同样100px的图片,在不同手机上显示的实际大小可能不同

Dp:这个是最常用但也最难理解的尺寸单位。它与“像素密度”密切相关,所以首先我们解释一下什么是像素密度。假设有一部手机,屏幕的物理尺寸为1.5英寸x2英寸,屏幕分辨率为240x320,则我们可以计算出在这部手机的屏幕上,每英寸包含的像素点的数量为240/1.5=160dpi(横向)或320/2=160dpi(纵向),160dpi就是这部手机的像素密度,像素密度的单位dpiDots Per Inch的缩写,即每英寸像素数量。横向和纵向的这个值都是相同的,原因是大部分手机屏幕使用正方形的像素点。不同的手机/平板可能具有不同的像素密度,例如同为4寸手机,有480x320分辨率的也有800x480分辨率的,前者的像素密度就比较低。Android系统定义了四种像素密度:低(120dpi)、中(160dpi)、高(240dpi)和超高(320dpi),它们对应的dppx的系数分别为0.7511.52,这个系数乘以dp长度就是像素数。例如界面上有一个长度为“80dp”的图片,那么它在240dpi的手机上实际显示为80x1.5=120px,在320dpi的手机上实际显示为80x2=160px

Sp:与刻度无关的像素)放大像素– 主要处理字体的大小。

 

30Android sqlite3是否支持并发访问

sqlite3数据库是一个数据库一个文件,所以当多进程访问操作同一数据库时,即与操作同一文件一样,文件锁问题。
对同个数据库进行多进程同时读是允许的,但多进程同时写是不允许的,如果一个进程已经正在写,其他进程就会写失败。sqlite3返回信息就是"Database is locked",错误码SQLITE_BUSYsqlite3对高并发访问支持不好,多线程访问数据库会出现数据库锁定现象。

 

31如何保证service在后台不被kill

和其他的应用组件一样,运行在进程的主线程中。这就是说如果service需要很多耗时或者阻塞的操作,需要在其子线程中实现(或者用系统提供的IntentService,它继承了Service,它处理数据是用自身新开的线程)。【当然你也可以在新的线程中startService,这样Service就不是在MainThread

 

 

32Requestlayout,onlayout,onDraw,DrawChild区别与联系

当一个View调用requestLayout的时候,会给当前的View设置一个FORCE_LAYOUT标记。由此向ViewParent请求布局。这样从这个View开始向上一直requestLayout。最终到达ViewRootImpl。ViewParent 就是当前的传输链。【参见职责链设计模式】

第一步。

ViewRootImpl发现请求了布局。那么就会调用measure方法。

measure方法确认当前View是否有FORCE_LAYOUT标记。

如果有,那么就会进行重新measure。并且设置标记LAYOUT_REQUIRED。

 

 

 

 

 

33Android之AsyncTask

AsyncTask的执行分为四个步骤
onPreExecute():当任务执行之前开始调用此方法,可以在这里显示进度对话框
doInBackground(Params...)此方法在后台线程执行,完成任务的主要工作,通常需要较长
的时间。执行过程中可以调用public Progress(Progress...)来更新任务的进度
onProgressUpdate(Progress...)此方法在主线程执行,用于显示任务执行的进度。
onPostExecute(Result)此方法在主线程执行,任务执行的结果作为此方法的参数返回
AsyncTask的三个泛型参数说明(三个参数可以是任何类型)

第一个参数:传入doInBackground()方法的参数类型
第二个参数:传入onProgressUpdate()方法的参数类型
第三个参数:传入onPostExecute()方法的参数类型,也是doInBackground()方法的返回类型


使用AsyncTask类,遵守的准则:1  Task的实例必须在UI thread中创建;2  Execute方法必须在UI thread中调用3  不要手动的调用onPfreexecute()onPostExecute(result)Doinbackground(params…),onProgressupdate(progress…)这几个方法;4  task只能被执行一次,否则多次调用时将会出现异常;
AsyncTask的整个调用过程都是从execute方法开始的,一旦在主线程中调用execute方法,就可以通过onpreExecute方法,这是一个预处理方法,比如可以在这里开始一个进度框,同样也可以通过onprogressupdate方法给用户一个进度条的显示,增加用户体验;最后通过onpostexecute方法,相当于handler处理UI的方式,在这里可以使用在doinbackground得到的结果处理操作UI。此方法在主线程执行,任务执行的结果作为此方法的参数返回

 

34IntentService

不管是何种Service,它默认都是在应用程序的主线程(亦即UI线程)中运行的。所以,如果你的Service将要运行非常耗时或者可能被阻塞的操作时,你的应用程序将会被挂起,甚至会出现ANR错误。为了避免这一问题,你应该在Service中重新启动一个新的线程来进行这些操作。现有两种方法共大家参考:

① 直接在Service的onStartCommand()方法中重启一个线程来执行;

② Android SDK 中为我们提供了一个现成的Service类来实现这个功能,它就是IntentService,它主要负责以下几个方面:

 

·生成一个默认的且与主线程互相独立的工作者线程来执行所有传送至 onStartCommand() 方法的Intetnt

·生成一个工作队列来传送Intent对象给你的onHandleIntent()方法,同一时刻只传送一个Intent对象,这样一来,你就不必担心多线程的问题。

·在所有的请求(Intent)都被执行完以后会自动停止服务,所以,你不需要自己去调用stopSelf()方法来停止该服务

·提供了一个onBind()方法的默认实现,它返回null

·提供了一个onStartCommand()方法的默认实现,它将Intent先传送至工作队列,然后从工作队列中每次取出一个传送至onHandleIntent()方法,在该方法中对Intent对相应的处理

从以上看来,你所需要做的就是实现 onHandleIntent() 方法,在该方法内实现你想进行的操作。另外,继承IntentService时,你必须提供一个无参构造函数,且在该构造函数内,你需要调用父类的构造函数;

 

35Android Service与Activity之间通信的几种方式

· 通过Binder对象

 

· 通过broadcast(广播)的形式

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(面试)