安卓面试小结.

安卓面试小结:

1.Retrofit框架的结构是什么?底层是怎么实现的?

简述:(这里可能理解不到位,链接里面比较详细)

Retrofit是对okhttp的进一步封装,它使用的是动态代理的技术,通过扫描注解构造请求体,底层使用okhttp进行网络请求,利用handler进行异步操作.

底层具体实现 : Retrofit2.0源码解析


2.网络框架是如何搭建的?Okhttp的底层实现是什么,和Retrofit有什么不同?

(1)Android学习之——自己搭建Http框架(1)

(2)Okhttp流处理底层使用了okio,具体实现推荐看看 OkHttp3源码分析[综述]

(3)Rtrofit就是对Okhttp进一步的封装,请求体通过注解的形式逐步传入,Rtrofit会自动封装,底层网络请求同样使用的是okhttp,它与Rxjava搭配更灵活.

以上是简单概括,给个鸿洋大神连接: Retrofit2 完全解析 探索与okhttp之间的关系


3.图片加载框架Glide,Picasso,Fresco有什么不同,各自的实现原理是什么?如何搭建一个网络框架?

Picasso:Square公司出品.

底层网络请求使用的是okhttp.  

优点:体积小,使用简单.图片默认RGB_8888

尺寸大,不支持gif,对大图片加载不方便.它底层实现就是对Handler进行的高效封装。

Gilde:Google出品.

使用方法和picasso十分相像,支持gif,默认尺寸RGB_565.体积比Picasso大。

Fresco:Facebook出品

(1)使用的是android的匿名共享内存,不占用虚拟机内存,节约应用内存使用,避免oom,减少bitmap回收提高应用性能

(2)支持图片渐进加载

(3)可以设置图片任意一点为中心

(4)图片展示操作在native中,不在虚拟机避免oom

(5)支持gif

不足之处只能使用固定的控件SimpleDraweeView,体积太大

网络框架的搭建(讲道理我也没搞过)

若使用现有的api那就简单了(相当于二次封装)还是上连接吧 Android学习之——自己搭建Http框架(1)


4.冒泡 选择 插入 快速基本算法的实现,单链表,双链表,二叉树,队列数据结构的实现思路是什么?

冒泡:


选择:


插入:


快速:


(下面的是个人理解)

单链表,双链表,二叉树,不借助其它的工具类实现.由于java没有指针这个东西,我们可以搞一个对象:

单链表:p.next(p);

双链表:p.front(p); p.next(p);

二叉树:p.front(p); p.left(p); p.right(p);

类似上面这种形式,当然也可以借助LinkedhashMap这类的集合类


5.如何实现跨进程通信,什么事AIDL,IPC机制,Binder机制的实现的原理

语言表达不行直接上超链接:

(1)AIDL,广播,Content Provider,访问其他应用程序的Activity

(2)AIDL : Android:学习AIDL,这一篇文章就够了(上)

                   Android:学习AIDL,这一篇文章就够了(下)

小Demo :  安卓漫漫路之AIDL传递简单数据. 

(3)IPC  :  Android开发艺术探索 第2章 IPC机制 读书笔记

(4)Binder :  Binder 牌胶水


6.三级缓存的底层实现?

(1)内存缓存

内存大小为应用内存大小的1/8, 底层使用的是LruCache,最近最最少使用算法,使用的是双向链表的数据结构(LinkedHashMap). 即最常使用的和新插入的数据会保存在链表头部,不常使用的数据会在链表尾部.若链表存满则删除链表尾部最后的元素,在头部插入新元素.

(2)本地缓存

底层使用的是DiskLruCache同为最近最最少使用算,也是是双向链表的数据结构(LinkedHashMap)同上.

(3)网络缓存

在服务端进行的缓存,若客户端无内存缓存,本地缓存则请求网络,若服务器有缓存则直接返回缓存数据,未缓存,则直接返回请求数据并缓存.

三级缓存顺序:

内存缓存->本地缓存->网络缓存

l  发送网络请求前先验证内存缓存是否有缓存数据 , 有则直接从内存中取,否则验证本地缓存。

l  内存缓存无缓存数据,验证本地缓存,本地缓存有则取出本地缓存数据,并缓存进内存缓存。若无缓存则请求网络。

l  本地缓存无缓存数据则通过网络请求服务器,并将换回的数据缓存到内存和本地


7.通过开源框架的源码分析如ButterKnife,EventBus,GreenDao,Ormlite,Dragger2,实现原理是什么?

都是使用注解的形式来获取对象,但是不同于后端J2ee注解。它们不属于运行时注解,而是编译型注解,即他们在App编译时会通过扫描注解生成相关的代码。实际上就是通过注解帮我们自动生成了相关代码,例如ButterKnife我们通过向注解中传入控件id就可以获取到控件的实例,其实是ButterKnife帮我们做了findViewById的工作,这些代码会在编译时生成不会写入到class。而运行时注解则是在软件运行时通过反射拿到注解,这样的耗时操作会影响软件速度如xutils。

(这里是个人理解,不对请您指正 )


8.HashMap底层实现,它和LinkHashMap有什么区别?

hashMap底层是哈希表数据结构,允许存入null键null值,该集合是不同步的,将hashtable替代。

LinkhashMap继承 hashMap,它具有HashMap的特性,但是它底层是双向链表结构,插入移除元素更加的快速,灵活性比HashMap更强。

AsycTask机制,实现原理:

对Handler高度封装,避免了手动开辟子线程,实现异步操作。

下面是简单的AsycTask机制源码分析:

初始化AsyncTask对象时,内部会得到mWorker和mFuture两个对象,mWorker是一个callable对象,它里面主要是对传入的数据进行操作操作(内部会调用doInBackground(),onProgressUpdate()方法)。mFuture对象传入了mWorker,mFuture它是一个Runnable接口,这个对象最终会交给线程池,处理mWorker中数据的相关操作。

执行execute()方法时会调用内部的executeOnExecutor(Excutor exec,Params... params)方法,首先内部会先执行onPreExecute()方法。接着执行exec.execute(mFuture),exec是executeOnExecutor的第一个参数,见名知意它就是传入的线程池变量,它是在Executor类中初始化好的final型变量直接传入executeOnExecutor方法的,这一步就是将mFuture扔给线程池。接下来会执行mFuture(Runnable)中的run方法,run方法中会调用Sync内部类的innerRun()方法,里面会执行callable.call()就是mWorker的call方法,call方法中会调用postResult(doInBackground()),在进入这个方法就会发现它里面就是通过handler将doInBackground()的结果发送到主线程,由InternalHandler接收,若结果为MESSAGE_POST_RESULT执行onPostExecute()并关闭AsyncTask任务。若为MESSAGE_POST_PROGRESS则执行onProgressUpdate()方法,只有在doInBackground()方法中调用publishProgress()方法才会有MESSAGE_POST_PROGRESS这个结果,onProgressUpdate()方法才会接收到数据。

以上分析的是3.0版本以后的源码,和3.0之前区别是:

3.0之前:

只能同时执行5个线程,线程池大小为128,若达到5个线程,开启第6个线程则会进入等待队列,当线程数量超过128个时直接崩溃

3.0之后

默认的线程池,同时只能执行1个线程。但是这个线程池可自定义,就是说自定义可以同时执行n条线程,大小为m。n,m并不是越大越好。比3.0之前固定的线程池更灵活。

弊端:

 容易内存泄漏,例如下载一个文件,有进度显示,在下载未下载完毕直接退出Activity的话AsyncTask并不会关闭任务,这样一来就会导致Activity得不到释放。就是它不方便关闭。


9.Handler消息机制,postDelayed会造成线程阻塞吗?对内存有什么影响?

上图:


不管在主线程还是在子线程想要通过handler发送消息必须要有Looper对象,在子线程中可通过Looper.prepare()获取,而在主线程中默认会被创建这个不用操心,为什么请百度Activity的源代码。

在条件都满足的情况下由handler发送消息,经过一系列的函数最终会进入到sendMessageAtTime()这个函数,说白了这个函数就是构建MssageQueue这个消息池,通过时间排序。之后就是我们的Looper对象了,它内部有一个死循环,在死循环内部有一个dispatchMessage()方法(属于handler的方法),这个方法就是根据时间顺序分发MssageQueue中的消息,也就是调用handleMessage()方法。

以上是粗略分析,详情还要看源代码。


10.Debug和Release状态的区别?

  链接:Android签名详解(debug和release)

debug签名和release签名的区别:

1)debug签名的应用程序不能在Android Market上架销售,它会强制你使用自己的签名;Debug模式下签名用的证书(默认是Eclipse/ADT和Ant编译)自从它创建之日起,1年后就会失效。

2)debug.keystore在不同的机器上所生成的可能都不一样,就意味着如果你换了机器进行apk版本升级,那么将会出现上面那种程序不能覆盖安装的问题,相当于软件不具备升级功能!


如有问题请多指正,您的指正使我更正确的前行.



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值