Android 工程师面试后的总结面试贴士

/ 华南女子学院面试贴士 / 2016-05-20

“基础 Android 知识掌握的不错,学习能力也不错。但是基础知识部分比较薄弱,有些概念和逻辑掌握不清。” 感谢前辈的这句话。

        Android开发,面试经验

MVC,MVP 和 MVVM


MVC 通信方式,环形方式:


1、View 传送指令到 Controller

2、Controller 起到不同层面间的组织作用,用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据 Model 上的改变。

3、Model 将新的数据发送到 View,用户得到反馈


所有通信都是单向的。
Android开发,面试经验

MVP 通信方式:


  1. 各部分之间的通信,都是双向的。

  2. View 与 Model 不发生联系,都通过 Presenter 传递。

  3. View 非常薄,不部署任何业务逻辑,称为”被动视图”(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。

MVVM 模式是 MVP 的升级:


基本上与 MVP 模式完全一致。唯一的区别是,它采用双向绑定:View的变动,自动反映在 ViewModel,反之亦然。
Android开发,面试经验

我们针对业务模型,建立的数据结构和相关的类,就可以理解为AndroidApp 的 Model,Model 是与 View 无关,而与业务相关的,例如数据库读取数据,应该是属于model层的事情。


我的猜想:


至于为什么我们通常直接去在 Activity 中去写数据库数据读取,我的猜想是因为简单。试想,如果是为了规范,首先定义一个getDataFromDB()的接口,再写个类实现getDataFromDB()方法,以后如果改了请求数据所用的方法,直接改写实现类,听起来确实不错,可是仅仅是为了从数据库读点数据,额外添加了至少两个类文件真的有意义吗。


当然网络请求,是属于业务逻辑层C层。


MVP中 Presenter 真正需要处理的并非业务逻辑,而应该是视图逻辑。业务逻辑应该是视图无关的,可以是单独的一个类中,也可以是在P中。


P与V是一对多关系


EventBus应该作用于P层,在P层发送,在P层接收。


MVVM中,M层改变并不是直接改变V层,而是通过VM层去改变V层。M与V依旧是不直接操作的。


架构的定义


有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计。


总结一下,就是一整个软件工程项目中的骨架,是一种宏观的规划。

Volley相关

Volley的磁盘缓存

在面试的时候,聊到 Volley 请求到网络的数据缓存。当时说到是 Volley 会将每次通过网络请求到的数据,采用FileOutputStream,写入到本地的文件中。

那么问题来了:这个缓存文件,是声明在一个SD卡文件夹中的(也可以是getCacheFile())。如果不停的请求网络数据,这个缓存文件夹将无限制的增大,最终达到SD卡容量时,会发生无法写入的异常(因为存储空间满了)。

这个问题的确以前没有想到,当时也没说出怎么回事。回家了赶紧又看了看代码才知道,原来 Volley 考虑过这个问题(汗!想想也是)


翻看代码

    DiskBasedCache#pruneIfNeeded() private void pruneIfNeeded(int neededSpace) {    if ((mTotalSize + neededSpace) < mMaxCacheSizeInBytes) {        return;    }     long before = mTotalSize;    int prunedFiles = 0;    long startTime = SystemClock.elapsedRealtime();     Iterator<Map.Entry<String, CacheHeader>> iterator = mEntries.entrySet().iterator();    while (iterator.hasNext()) {        Map.Entry<String, CacheHeader> entry = iterator.next();        CacheHeader e = entry.getValue();        boolean deleted = getFileForKey(e.key).delete();        if (deleted) {            mTotalSize -= e.size;        } else {    //print log        }        iterator.remove();        prunedFiles++;        if ((mTotalSize + neededSpace) < mMaxCacheSizeInBytes * HYSTERESIS_FACTOR) {            break;        }    }}

其中mMaxCacheSizeInBytes是构造方法传入的一个缓存文件夹的大小,如果不传默认是5M的大小。


通过这个方法可以发现,每当被调用时会传入一个neededSpace,也就是需要申请的磁盘大小(即要新缓存的那个文件所需大小)。首先会判断如果这个neededSpace申请成功以后是否会超过最大可用容量,如果会超过,则通过遍历本地已经保存的缓存文件的header(header中包含了缓存文件的缓存有效期、占用大小等信息)去删除文件,直到可用容量不大于声明的缓存文件夹的大小。


其中HYSTERESIS_FACTOR是一个值为0.9的常量,应该是为了防止误差的存在吧(我猜的)。

$.get("/basic/1648/hit.do");


公众号,微信

汇鱼网海峡创乐汇
汇鱼网海峡创乐汇