android面试题(未完)

简单描述下android数字签名

android数字证书包含以下几个要点:

(1)所有的应用程序都必须有数字证书,android不会安装一个没有数字证书的应用,此数字证书用于标识应用程序的作者和在应用程序之间建立信任关系,不是用来决定最终用户可以安装哪些应用程序,数字证书的私钥则保存在程序开发者手中。

(2)android程序使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签名认证。

(3)如果要正式发布一个android应用,必须使用一个合适的私钥生成的数字证书来给程序签名,而不能使用adt插件或者ant工具生成的调试证书来发布。

(4)数字证书都是有有效期的,android只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能。

android生命周期相关


横竖屏幕切换时activity的生命周期

这个生命周期跟清单文件里的配置有关

(1)不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次。

(2)设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次,但竖屏时执行一次后多执行一次onConfigurationChanged。

(3)设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法,横屏时执行一次,竖屏时执行两次。

参考:http://blog.csdn.net/wulianghuan/article/details/8603982

(另:游戏开发中,屏幕的方向都是写死的)

你后台的activity被系统回收了怎么办?如何在activity被回收前保存当前状态以便重启恢复?

除了在栈顶的activity,其他的activity都有可能在内存不足的时候被系统回收。一个activity越处于栈底,被回收的可能性越大。

只需重写onSaveInstanceState()方法,在此方法中将Activity的状态信息键值对形式存放在bundle对象中,该方法将会在activity被回收之前调用。通过重写onRestoreInstanceState()方法可以从中提取保存好的数据。

onSaveInstanceState和onRestoreInstanceState触发的时机

onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了)。至于onRestoreInstanceState方法,需要注意的是,onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成对的被调用的,onRestoreInstanceState被调用的前提是,activity A“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity A,这种情况下activity A一般不会因为内存的原因被系统销毁,故activity A的onRestoreInstanceState方法不会被执行,另外,onRestoreInstanceState的bundle参数也会传递到onCreate方法中,你也可以选择在onCreate方法中做数据还原。

参考:http://android.blog.51cto.com/268543/634646/

android四大组件相关

参考(简答):http://blog.csdn.net/ican87/article/details/21874321

参考(超详细):http://www.cnblogs.com/pepcod/archive/2013/02/11/2937403.html

1.HttpURLConnection和HttpClient他们各自的优缺点是什么? 
HttpUrlConnection 在 2.3 以前的版本是有 bug 的,所以之前的版本推荐使用 HttpClient,但是 google 现在已经不维护 HttpClient 了,5.1里面已经把 HttpClient 标过期。另外 HttpURLConnection 支持gzip压缩等,推荐首选它。 
在 Froyo(2.2) 之前,HttpURLConnection 有个重大 Bug,调用 close() 函数会影响连接池,导致连接复用失效,所以在 Froyo 之前使用 HttpURLConnection 需要关闭 keepAlive。 
另外在 Gingerbread(2.3) HttpURLConnection 默认开启了 gzip 压缩,提高了 HTTPS 的性能,Ice Cream Sandwich(4.0) HttpURLConnection 支持了请求结果缓存。 
再加上 HttpURLConnection 本身 API 相对简单,所以对 Android 来说,在 2.3 之后建议使用 HttpURLConnection,之前建议使用 AndroidHttpClient。
2.Android开发中XML解析方式的比较 ,及优缺点? 
DOM,SAX,Pull解析。 
SAX解析器的优点是解析速度快,占用内存少;
DOM在内存中以树形结构存放,因此检索和更新效率会更高。但是对于特别大的文档,解析和加载整个文档将会很耗资源,不适合移动端;
PULL解析器的运行方式和SAX类似,都是基于事件的模式,PULL解析器小巧轻便,解析速度快,简单易用,非常适合在Android移动设备中使用,Android系统内部在解析各种XML时也是用PULL解析器。
3.请问平时开发过程中,你是如何做到多分辨率适配的? 
1.根据不同分辨率建立不同的布局文件 
2.根据分辨率不同建立不同分辨率的资源图片 
3.在程序启动时,获取当前屏幕的分辨率和密度,在代码中进行适配 
4.为不同分辨率的写不同的dimen文件。 
5.其实还有就是多使用fragement
4. 谈谈你在工作中是怎样解决一个bug的? 
1.看Log日志 
2.Log解决不了就断点调试 
3.如果debug不行 
4.就在异常代码的附近Log.e(“error”,”1”);,2,3,4,5,6,7,8,9 每隔一行一个Log输出,看结果 
5.找到问题,自行找思路。如果是技术瓶颈,就google之
5.声明ViewHolder内部类时,为什么建议使用static关键字? 
其实这个是考静态内部类和非静态内部类的主要区别之一。非静态内部类会隐式持有外部类的引用,就像大家经常将自定义的adapter在Activity类里,然后在adapter类里面是可以随意调用外部activity的方法的。当你将内部类定义为static时,你就调用不了外部类的实例方法了,因为这时候静态内部类是不持有外部类的引用的。声明ViewHolder静态内部类,可以将ViewHolder和外部类解引用。大家会说一般ViewHolder都很简单,不定义为static也没事吧。确实如此,但是如果你将它定义为static的,说明你懂这些含义。万一有一天你在这个ViewHolder加入一些复杂逻辑,做了一些耗时工作,那么如果ViewHolder是非静态内部类的话,就很容易出现内存泄露。如果是静态的话,你就不能直接引用外部类,迫使你关注如何避免相互引用。 所以将 ViewHolder内部类 定义为静态的,是一种好习惯. 
非静态内部类隐式持有外部类的强引用,只是可能会导致内存泄露,而一般情况下在使用viewhodler是不会导致内存泄露的,加static是一个比较好的习惯
6.如何在不失真的条件下显示一张超高清的图片或者长图? 
1、通过计算BitmapFactory.Options 对象的inSamleSize 值 等比的压缩图片 。 
2、使用WebView来加载该图片; 
3、使用MapView或者TileView来显示图片(类似地图的机制);
7. Android中有哪些方法实现定时和延时任务?它们的适用场景是什么? 
倒计时类 
用CountDownTimer
延迟类 
CountDownTimer,可巧妙的将countDownInterval设成和millisInFuture一样,这样就只会调用一次onTick和一次onFinish 
handler.sendMessageDelayed,可参考CountDownTimer的内部实现,简化一下,个人比较推荐这个 
TimerTask,代码写起来比较乱 
Thread.sleep,感觉这种不太好 
使用Handler方法postDelay(runnable, delayTime)
定时类 
参照延迟类的,自己计算好要延迟多少时间 
handler.sendMessageAtTime 
AlarmManager,适用于定时比较长远的时间,例如闹铃
8.谈谈你对StrongReference、WeakReference和SoftReference的认识 
强引用(StrongReference):就是在代码中普遍存在的,类似Object obj = new Object()这类的引用,只要强引用还存在,GC永远不会回收掉被引用的对象。 
软引用(SoftReference):用来描述一些还有用但非必须的对象。对于软引用关联着的对象,在系统将要发生内存溢出异常时,将会把这些对象列入回收范围之中进行第二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。在JDK 1.2之后,提供了SoftReference类来实习软引用。
弱引用(WeakReference):也是用来描述非必须对象的,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到了下一次GC发生之前。当GC工作时,无论当时内存是否足够,都会回收只被弱引用关联的对象。在JDK 1.2之后,提供了WeakReference类来实现弱引用。
虚引用(PhantomReference):这个引用po主没有提到,不过也可以顺带了解一下。虚引用也称幽灵引用或者幻影引用,它是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用的唯一目的就是在这个对象被GC回收是收到一个系统通知。在JDK 1.2之后提供了PhantomReference类来实现虚引用。
9.你应用中的网络层是怎么设计的? 
1. android-async-http. 
封装了下常用的方法,get post 上传 下载 ,所有的请求我都是用的同步请求. 
具体的用法一般都是和业务逻辑在一起,而我的业务逻辑是用异步去处理的. 
关于网络请求结果的缓存,我是单独处理的.并没有放在网络层.
2.在HttpUrlConnection基础上封装, 包括请求成功, 失败, 请求中, 网络问题等封装, 利用广播与UI交互 
3.直接使用xUtils,afinal,okHttp,Volley等开源第三方框架;
Service和广播 BroadcastReceivre会不会出现ANR? 
Service,广播 会出现ANR 
服务, 广播都是主线程中, 既然是主线程 当然会anr 所以耗时操作还是必须另起线程 
通俗的说超时时间:Activity 5秒, Broadcast 10秒, Server 20秒
你在平时开发中会使用到哪些设计模式,能谈谈这些设计模式的使用场景吗? 
平时用的比较多有单例模式(在内存中仅实例化一个对象时使用):DownloadManager,适配器模式(典型的就是ListView和GridView的适配器),建造者模式(AlertDialog.Builder),观察者模式可能比较隐蔽,在Android源码中BaseAdapater的NotifyDataSetChanged的实现

谈谈你对application的理解
其实说对什么的理解,就是考察你对这个东西会不会用,重点是有没有什么坑!
首先,Application在一个Dalvik虚拟机里面只会存在一个实例,所以你不要傻傻的去弄什么单例模式,来静态获取Application了,你把Application构造函数设置成privete都不可能实现。
那么为什么强调说是一个Dalvik虚拟机,而不是说一个App呢?
因为一个App有可能有多个Dalvik虚拟机,也就是传说中的多进程模式。在这种模式下,每一个Dalvik都会存在一个Application实例,他们之间没有关系,在A进程Application里面保存的数据不能在B进程的Application获取,因为他们根本不是一个对象,而且被隔离在了两个进程里面,所以这里强调是一个Dalvik虚拟机,而不是一个App。
其次,Application的实质是一个Context,它继承自ContextWrapper。
    android.content.Context
       ↳  android.content.ContextWrapper
        ↳ android.app.Application     
ContextWrapper是什么玩意?就是对Context的一个包装而已。
Application有两个子类,一个是MultiDexApplication,如果你遇到了"65535"问题,可以选择继承自他,完成多Dex打包配置的相关工作。
另外一个是在TDD(测试用例驱动)开发模式中使用Moke进行测试的时候用到的,可以来代替Application的Moke类MockApplication。
在应用启动的时候,会首先调用Application.attach(),当然,这个方法是隐藏的,开发者能接触到的第一个被调用的方法其实是Application.onCreate(),我们通常会在这个方法里面完成各种初始化,比如图片加载库、Http请求库的默认配置初始化操作等等。但是最好别在这个方法里面进行太多耗时操作,因为这会影响App的启动速度,所以对于不必要的操作可以使用异步操作、懒加载、延时加载等策略来减少对UI线程的影响。
除此之外,由于在Context中可以通过getApplicationContext()获取到Application对象,或者是通过Activity.getApplication()、Service.getApplication()获取到Application,所以可以在Application保存全局的数据,供所有的Activity或者是Service使用。
PS:使用上面的三种方法获取到的都是同一个Application对象,getApplicationContext()是在Context的实现类ContextImpl中具体实现的,而getApplication()则是在Activity和Service中单独实现的,所以他们的作用域不同,但是获取到的都是同一个Application对象,因为一个Dalvik虚拟机只有一个Application对象。
但是这里存在着一个坑,那就是在低内存情况下,Application有可能被销毁,从而导致保存在Application里面的数据信息丢失,最后程序错乱,甚至是Crash。
所以当你想在Application保存数据的时候,请做好为空判断,或者是选择其他方式保存你的数据信息。
另外,在Application中存在着几个有用的方法,比如onLowMemory()和onTrimMemory(),在这两个方法里面,我们可以实现自己的内存回收逻辑,比如关闭数据库连接、移除图片内存缓存等操作来降低内存消耗,从而降低被系统回收的风险。
最后,就是要注意Application的生命周期,他和Dalvik虚拟机生命周期一样长,所以在进行单例或者是静态变量的初始化操作时,一定要用Application作为Context进行初始化,否则会造成内存泄露的发生。使用Dialog的时候一般使用Activity作为Context,但是也可以使用Application作为上下文,前提是你必须设置Window类型为TYPE_SYSTEM_DIALOG,并且申请相关权限。这个时候弹出的Dialog是属于整个Application的,弹出这个Dialog的Activity销毁时也不会回收Dialog,只有在Application销毁时,这个Dialog才会自动消失。

Android为什么要设计出Bundle而不是直接使用HashMap来进行数据传递?

Bundle内部是由ArrayMap实现的,ArrayMap的内部实现是两个数组,一个int数组是存储对象数据对应下标,一个对象数组保存key和value,内部使用二分法对key进行排序,所以在添加、删除、查找数据的时候,都会使用二分法查找,只适合于小数据量操作,如果在数据量比较大的情况下,那么它的性能将退化。而HashMap内部则是数组+链表结构,所以在数据量较少的时候,HashMap的Entry Array比ArrayMap占用更多的内存。因为使用Bundle的场景大多数为小数据量,我没见过在两个Activity之间传递10个以上数据的场景,所以相比之下,在这种情况下使用ArrayMap保存数据,在操作速度和内存占用上都具有优势,因此使用Bundle来传递数据,可以保证更快的速度和更少的内存占用。
另外一个原因,则是在Android中如果使用Intent来携带数据的话,需要数据是基本类型或者是可序列化类型,HashMap使用Serializable进行序列化,而Bundle则是使用Parcelable进行序列化。而在Android平台中,更推荐使用Parcelable实现序列化,虽然写法复杂,但是开销更小,所以为了更加快速的进行数据的序列化和反序列化,系统封装了Bundle类,方便我们进行数据的传输。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值