Android面试宝典

来源:互联网 发布:晒书房 知乎 编辑:程序博客网 时间:2024/06/05 02:09

1.常用的存储方式有哪些?(概率50%)
(五种,说出哪五种,五种存储方式什么情况下用。)注意sharepreferes对象支持读取不支持写入,写入引用Editor。
SQLite:
SQLite是一个轻量级的数据库,支持基本SQL语法,是常被采用的一种数据存储方式。Android为此数据库提供了一个名为SQLiteDatabase的类,封装了一些操作数据库的API。
SharedPreference:
除SQLite数据库外,另一种常用的数据存储方式,其本质就是一个xml文件,常用于存储较简单的参数设置。
File:
即常说的文件(I/O)存储方法,常用语存储大数量的数据,但是缺点是更新数据将是一件困难的事情。
ContentProvider:
Android 系统中能实现所有应用程序共享的一种数据存储方式,由于数据通常在各应用间的是互相私密的,所以此存储方式较少使用,但是其又是必不可少的一种存储方式。例如音频,视频,图片和通讯录,一般都可以采用此种方式进行存储。每个ContentProvider都会对外提供一个公共的URI(包装成Uri对 象),如果应用程序有数据需要共享时,就需要使用ContentProvider为这些数据定义一个URI,然后其他的应用程序就通过 Content Provider传入这个URI来对数据进行操作。
网络存储:
从网络读取数据和写入数据。 Android提供了通过网络来实现数据的存储和获取的方法。
我们可以调用WebService返回的数据或是解析HTTP协议实现网络数据交互。

1:目前在国内网络上的资料数据的存储方式分别是: SQLite, SharedPreference, File, ContentProvider, 网络存储,但是,我去官方文档查了一下,谷歌给的存储方式分为这五种:
1: Shared Preferences(以键值对的形式存储私有的,简单数据类型)
2: Internal Storage(内存存储)(私有的数据存储在设备的内存里面)
3: External Storage(外部存储)(将公共的数据存储在SD卡里面)
4: SQLite Databases(数据库存储)(将数据存储在私有的数据库里面)
(数据库存储包括SQLite和ContentProvider,其实ContentProvider的底层就是在操作数据库)
5: Network Connection(网络连接)(存储数据在web端,在你自己的数据服务器上)

2.安卓中动画有几类,他们的特点和区别?(概率80%)
在国内的很多网站上动画都分为两种:帧动画和补间动画,但是在安卓的官网上在3.0,又加入一种属性动画.也就是现在有3种动画.
1: Property Animation(属性动画别加入在3.0)
2: View Animation (补间动画分为:透明,旋转,位移,缩放)
注意:补间动画是假动画,比如一个位移从A移动到B,如果给他设置监听事件,他的点击区域永远都在A,但是属性动画,如果给他设置点击事件,同样从A移动到B,他的点击区域就在B.
3: Drawable Animation(帧动画帧动画类似于放电影,通过播放已经排列放好的图片来实现。)

两种,一种是补间动画,还有一种是帧动画,帧动画类似于放电影,通过播放已经排列放好的图片来实现。
补间动画的实现定义开始和结束,中间由系统计算得出效果有透明,位移,放大缩小等等。
自定义录音或者进度条过程,会应用到帧动画,补间动画,一般用于应用的欢迎界面。
(菜单弹出,例如赞和评论,是个动画过程。)
3.handler机制原理(概率100%)
在安卓中有4大组件:activity,service,contentprovider,broadcastreceiver,这4大组件都运行在主线,谷歌官方规定,安卓不能再主线程做耗时操作,负责会造成ANR,为了避免这种情况的出现,必须开线程处理耗时操作,但是安卓规定,子线程不能更新UI,所以安卓引入了Handler机制,
(因为安卓中的UI控件不是线程安全的,如果在多线程中,并发访问可能会导致UI控件处于不可预期的状态,(为啥系统不对UI控件的访问加锁机制,缺点有两个1:加上锁机制会让UI访问的逻辑变的复杂,其次锁机制会降低UI访问的效率,因为锁机制会阻塞某些线程的执行,最简单最高效就是采用单线程来处理,对于我们来说也不是很麻烦,只需要通过Handler切换一下UI访问的执行线程即可))
Handler主要用于线程间的通信。
一个Handler允许发送和处理Message和Runable对象,UI主线程会自动分配一个Looper(消息轮询器),每个Looper中封装着MessageQueue(消息队列),遵循先进先出原则。Looper负责不断的从自己的消息队列里取出队头的任务或消息执行。一般是在子线程执行完耗时操作之后,通过Handler的sendMessage或post方法将Message和Runable对象传递给MessageQueue,而且在这些对象离开MessageQueue时,Handler负责执行他们(用到handleMessage方法,主要执行刷新UI的代码)。
其中Message类就是定义了一个信息,这个信息中包含一个描述符和任意的数据对象,这个信息被用来传递给Handler.Message对象提供额外的两个int域和一个Object域。

字面以外加上关联点。
4除了handler和子线程,还有一个处理线程的是什么,主要方法是什么?(概率60%)
AsynTask,doInbackGround+onPostExecute
doInBackground() 这个方法运行在后台线程中,主要负责执行那些很耗时的操作,如访问网络。该方法必须重写。
onPostExecute(Result) 这个方法运行于UI主线程,在doInBackground(Params…)方法执行后调用,该方法用于接收后台任务执行后返回的结果,刷新UI显示
5.tcp和udp区别.(概率80%)
TCP—(长链接)(管发管收,数据安全)传输控制协议,提供的是面向连接、可靠的字节流服务,传输数据前经过“三次握手”建立连接,保证数据传输的可靠性,但效率比较低。一般用于对于数据传输安全性较高的场合。
UDP—(短连接,只管发,不管收,想聊天就是UDK,丢了几句聊天记录无所谓)用户数据报协议,是一个简单的面向数据报的运输层协议,面向无连接。UDP不提供可靠性,数据传输可能发生错序,丢包,但效率较高。一般用于对于实时性要求较高的场合。
6线程之间的通信方式(如何避免ANR)(概率70%)
(1). AsyncTask,其中doInBackground()和onPostExecute(Result)两个方法非常重要
doInBackground() 这个方法运行在后台线程中,主要负责执行那些很耗时的操作,如访问网络。该方法必须重写。(其实这个方法就是在子线程中做耗时操作,通过handler发送到onPostExecute)
onPostExecute(Result) 这个方法运行于UI主线程,在doInBackground(Params…)方法执行后调用,该方法用于接收后台任务执行后返回的结果,刷新UI显示。
(2.)子线程 + handler
在子线程中执行完耗时操作需要刷新UI时,通过handler.sendMessage()发消息给主线程, 然后在主线程Handler中的handleMessage()方法中执行刷新UI操作
7.activity的生命周期(概率80%)
(可见安卓开发艺术与探索) // 开始 重新启动 停止 销毁 暂停
七个,oncreate,onstart,onrestart,onstop,onresume,ondestroy,onpause;(清楚整个周期的过程)
1).启动Activity:系统会先调用onCreate方法,然后调用onStart方法,最后调用onResume,Activity进入运行状态(onStart在页面没有获取焦点之前执行, onResume在页面获取焦点时执行,一般情况下网络请求放在onResume方法中,这样做到目的是负责在当前页面上的页面结束后,当前页面也快及时更新数据)。
2).当前Activity被其他Activity覆盖其上或被锁屏:系统会调用onPause方法,暂停当前Activity的执行。
3).当前Activity由被覆盖状态回到前台或解锁屏:系统会调用onResume方法,再次进入运行状态。
4).当前Activity转到新的Activity界面或按Home键回到主屏,自身退居后台:系统会先调用onPause方法,然后调用onStop方法,进入停滞状态。
5).用户后退回到此Activity:系统会先调用onRestart方法,然后调用onStart方法,最后调用onResume方法,再次进入运行状态。
6).当前Activity处于被覆盖状态或者后台不可见状态,即第2步和第4步,系统内存不足,杀死当前Activity,而后用户退回当前Activity:再次调用onCreate方法、onStart方法、onResume方法,进入运行状态。
7).用户退出当前Activity:系统先调用onPause方法,然后调用onStop方法,最后调用onDestory方法,结束当前Activity。
Activity 有七个生命周期
一般情况下创建一个activity首先会执行onCreate,onStart,onResume,onPause,onStop,onDestory,这个时候我们一般将访问网络放在onResume里面,
onCreate :activity 第一次创建的时候被执行,
onStart :在启动但没有获取焦点之前执行,无法与用户进行交互
onResume :在获取到焦点的时候执行,同时可以操作页面
onPause :activity正在失去焦点的时候执行
onStop :失去焦点以后执行
onDestory:页面销毁的时候执行,
比如刚刚创建一个activity,首先会执行onCreate, onStart, onResume,这个时候跳转到其他activity,当前activity首先会执行onPause, onStop,(但是如果另外一个activity采用了透明的主题,当前activity不会回调onStop),其他activity执行onCreate, onStart, onResume,这个时候结束掉其他activity,当前activity会执行onRestart, onStart, onResume

8.ArrayList和LinkedList区别?(概率30%)
存数据,ArrayList数组存储数据,索引值以下标来搜索,查询比较方,删除增加比较麻烦,但是linkedList以链表式存储数据,对于增删比较方便。

ArrayList和LinkedList在性能上各 有优缺点,都有各自所适用的地方,总的说来可以描述如下:

对ArrayList和LinkedList而言,在列表末尾增加一个元素所花的开销都是固定的。对 ArrayList而言,主要是在内部数组中增加一项,指向所添加的元素,偶尔可能会导致对数组重新进行分配;而对LinkedList而言,这个开销是 统一的,分配一个内部Entry对象。在ArrayList的 中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动;而在LinkedList的中间插入或删除一个元素的开销是固定的。LinkedList不 支持高效的随机元素访问。ArrayList的空 间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间可以这样说:当操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能;当你的操作是在一列数据的前面或中 间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。

9.安卓内存的优化?(概率90%)
http://blog.csdn.net/awangyunke/article/details/20380719
handler内存泄露(thread, AsyncTask)
http://www.linuxidc.com/Linux/2013-12/94065.htm
context内存泄露
http://blog.sina.com.cn/s/blog_5da93c8f0102w86x.html
Bitmap内存泄露

1)静态变量引起内存泄露(内存泄露多了就变成溢出)
在代码优化的过程中,我们需要对代码中的静态变量特别留意。静态变量是类相关的变量,它的生命周期是从这个类被声明,到这个类彻底被垃圾回收器回收才会被销毁。所以,一般情况下,静态变量从所在的类被使用开始就要一直占用着内存空间,直到程序退出。如果不注意,静态变量引用了占用大量内存的资源,造成垃圾回收器无法对内存进行回收,就可能造成内存的浪费
2)使用Application(单例模式)的Context
在Android中,Application Context的生命周期和应用的生命周期一样长,而不是取决于某个Activity的生命周期。如果想保持一个长期生命的对象,并且这个对象需要一个 Context,就可以使用Application对象。可以通过调用Context.getApplicationContext()方法或者 Activity.getApplication()方法来获得Application对象。
3)及时关闭资源
Cursor是Android查询数据后得到的一个管理数据集合的类。正常情况下,如 果我们没有关闭它,系统会在回收它时进行关闭,但是这样的效率特别低。如果查询得到的数据量较小时还好,如果Cursor的数据量非常大,特别是如果里面 有Blob信息时,就可能出现内存问题。所以一定要及时关闭Cursor。
4)使用Bitmap及时调用recycle() // 把 重复循环的方法设置 为 null,释放内存
前面的章节讲过,在不使用Bitmap对象时,需要调用recycle()释放内存,然后将它设置为null。虽然调用recycle()并不能保证立即释放占用的内存,但是可以加速Bitmap的内存的释放。
在代码优化的过程中,如果发现某个Activity用到了Bitmap对象,却没有显式的调用recycle()释放内存,则需要分析代码逻辑,增加相关代码,在不再使用Bitmap以后调用recycle()释放内存。
5)对Adapter进行优化
下面以构造ListView的BaseAdapter为例说明如何对Adapter进行优化。
@软引用和弱引用。
如果一个对象只具有软引用,那么如果内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
如果一个对象只具有弱引用,那么在垃圾回收器线程扫描的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。弱引用也可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联 的引用队列中。
弱引用与软引用的根本区别在于:只具有弱引用的对象拥有更短暂的生命周期,可能随时被回收。而只具有软引用的对象只有当内存不够的时候才被回收,在内存足够的时候,通常不被回收。
6)UI优化
在Android应用开发过程中,屏幕上控件的布局代码和程序的逻辑代码通常是分开 的。界面的布局代码是放在一个独立的xml文件中的,这个文件里面是树型组织的,控制着页面的布局。通常,在这个页面中会用到很多控件,控件会用到很多的 资源。Android系统本身有很多的资源,包括各种各样的字符串、图片、动画、样式和布局等等,这些都可以在应用程序中直接使用。这样做的好处很多,既 可以减少内存的使用,又可以减少部分工作量,也可以缩减程序安装包的大小。
10.framgment生命周期?(概率30%)
oncreate,onstart,onrestart,onstop,onresume,ondestroy,onpause,onAttach,onCreateView,onDettach,onDestroyView;(和activity的生命周期比较,会更好)
MyFragment onAttach() 粘贴到activity上
MyFragment onCreate() fragment创建
MyFragment onCreateView() fragment创建自己的视图
MainActivity onCreate()
MyFragment onActivityCreated() 可以处理fragment数据的初始化
MainActivity onStart()
MyFragment onStart()
MainActivity onResume()
MyFragment onResume()
按后退键
MyFragment onPause()
MainActivity onPause()
MyFragment onStop()
MainActivity onStop()
MyFragment onDestoryView() 销毁掉自己的视图
MyFragment onDestory()
MyFragment onDetach() 解除和activity的关系
MainActivity onDestory()
11·图片异步加载怎么做?(概率80%)
三级缓存:
1:首先从强引用中获取(Lrucache),如果强引用中没有,再去软引用中获取(SoftReference),如果软引用再去SD卡获取(SD卡被Dis Lrucache替代掉),如果这三级缓存中都没有,就开启网络去请求图片,请求回来的图片,在加入到强引用中(Lrucache),如果强引用已经满了,这时候,强引用通过Lrucache算法,删除掉一些最近不常用的图片,这时候咱们把这些图片放到软引用里面,(当内存不足到时候软引用就会被被垃圾回收机制回收),如果垃圾回收机制没有,软引用也满了,将不常用的图片移除掉,同时加入到SD卡,(现在被Dis Lrucache替代)
(key 一般使用的是网络请求图片的url,来保证唯一性,一般情况下我会做一下MD5加密,这样做的目的是为了保证不会出现非法字符)

现在SoftReference已经被替代掉,现在我们只使用两级缓存,在加网络, Lrucache, Dis Lrucache
LRC算法:最近最少使用的(内部如何实现的)
强引用: Lrucache
软引用: SoftReference
弱引用:weak(随时被垃圾回收机制回收)
虚引用:phantomreference

可定义图片异步加载工具类,核心方式实现思路如下:
1.先从内存缓存(Map

define SENSOR_TYPE_ACCELEROMETER 1 //加速度

define SENSOR_TYPE_MAGNETIC_FIELD 2 //磁力

define SENSOR_TYPE_ORIENTATION 3 //方向

define SENSOR_TYPE_GYROSCOPE 4 //陀螺仪

define SENSOR_TYPE_LIGHT 5 //光线感应

define SENSOR_TYPE_PRESSURE 6 //压力

define SENSOR_TYPE_TEMPERATURE 7 //温度

define SENSOR_TYPE_PROXIMITY 8 //接近

define SENSOR_TYPE_GRAVITY 9 //重力

define SENSOR_TYPE_LINEAR_ACCELERATION 10//线性加速度

define SENSOR_TYPE_ROTATION_VECTOR 11//旋转矢量

121.SurfaceView实现的原理(概率80%)
SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面。由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独立的线程中进行行绘制。又由于不占用主线程资源,SurfaceView一方面可以实现复杂而高效的UI,另一方面又不会导致用户输入得不到及时响应。
122.Int Integer的区别 (概率30%)
int 是基本类型,直接存数值

1.Java 中的数据类型分为基本数据类型和复杂数据类型
int 是前者>>integer 是后者(也就是一个类)
2.初始化时>>
int i =1;
Integer i= new Integer(1);(要把integer 当做一个类看)
int 是基本数据类型(面向过程留下的痕迹,不过是对java的有益补充)
Integer 是一个类,是int的扩展,定义了很多的转换方法
类似的还有:float Float;double Double;string String等

123.Application类的作用(概率60%)
Application和Actovotu,Service一样是android框架的一个系统组件,当android程序启动时系统会创建一个 application对象,用来存储系统的一些信息。通常我们是不需要指定一个Application的,这时系统会自动帮我们创建,如果需要创建自己 的Application,也很简单创建一个类继承 Application并在manifest的application标签中进行注册(只需要给Application标签增加个name属性把自己的 Application的名字定入即可)。
android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,所以Application可以说是单例 (singleton)模式的一个类.且application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局 的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象。所以通过Application来进行一些,数据传递,数据共享 等,数据缓存等操作。

124.嵌入式操作系统(概率20%)
嵌入式实时操作系统是指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快速响应,并控制所有实时任务协调一致运行的嵌入式操作系统。主要用于工业控制、军事设备、航空航天等领域对系统的响应时间有苛刻的要求,这就需要使用实时系统。又可分为软实时和硬实时两种,而android是基于linux内核的,因此属于软实时。

125.ViewFlipper和ViewPager的区别(概率30%)
1.ViewFilpper类继承于ViewAnimator类。而ViewAnimator类继承于FrameLayout。
查看ViewAnimator类的源码可以看出此类的作用主要是为其中的View切换提供动画效果。该类有如下几个和动画相关的方法。
2.ViewPager用于实现多页面的切换效果,该类存在于Google的兼容包里面,所以在引用时记得在BuilldPath中加入“android-support-v4.jar”

126.定义数组的几种方式(概率30%)
int a[]; //声明未初始化
a = new int [10]; // 定义占用空间大小(10个int)
int a[] = new int [10]; //声明并定义大小(即分配了指定大小的空间)
int a[] = {1,2,3}; // 声明并初始化,占用空间大小是3个int。

127.知道哪几种排序方式(概率90%)
冒泡
public static int[] doMaoPao(int[] in){
int temp;
int length = in.length;
for(int i = 0;i