以下这些面试题都是笔者在(2017年1月-2017年3月)这段时间所面试Android工程师的总结而来,面试的公司包括巨头xx等,还有新贵公司如dd在线科技,gm金融,zk网,momo科技,zbj等,还有小型活力公司如软都科技,星云颜值,英克科技等,不足之处,还望各位不吝赐教。

1.谈一谈MVC,MVP,MVVM模式的理解。

第一次遇到这个问题,笔者只能悻悻的回答MVC模式,其他没法展开说,后来总结记下来,下次遇到so easy(面试遇到两次该问题)。

一、 MVC

MVC模式的意思是,软件可以分成三个部分。

各部分之间的通信方式如下。

1.View 传送指令到 Controller
2.Controller 完成业务逻辑后,要求 Model 改变状态
3.Model 将新的数据发送到 View,用户得到反馈

所有通信都是单向的。

二、MVP

MVP 模式将 Controller 改名为 Presenter,同时改变了通信方向。

1. 各部分之间的通信,都是双向的。
2. View 与 Model 不发生联系,都通过 Presenter 传递。
3. View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。

三、MVVM

MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。

唯一的区别是,它采用双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之亦然。

关于data-binding的用法,可以看看这篇文章 完全掌握Android Data Binding

2.自定义view需要重写哪些方法,如何设定自定义view固定宽高比,如何自定义属性标签?


自定义view需要重写onMeasure(),onLayout()(继承来自ViewGroup时需要),onDraw()。

在OnMeasure()方法中,如果是view的话,view的视图的最终大小确定通过调用setMeasuredDimension()来实现,在此处可以设置固定宽高比,如果是viewgroup的话,对其子视图进行遍历的measure()过程。

OnLayout()主要作用 :为将整个根据子视图的大小以及布局参数将View树放到合适的位置上。如果该View不是ViewGroup类型 ,调用setFrame()方法设置该控件的在父视图上的坐标轴,如果该View是ViewGroup类型,则对它的每个子View进行layout()过程。

OnDraw()方法中,首先绘制view背景,接着绘制视图本身,然后调用dispatchDraw ()方法绘制子视图,最后绘制滚动条。

自定义属性的使用:

一、在res/values文件下定义一个attrs.xml文件,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<resources> <declare-styleable name="ToolBar"> <attr name="buttonNum" format="integer"/> <attr name="itemBackground" format="reference|color"/> </declare-styleable>
</resources>

二、在布局xml中如下使用该属性:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:toolbar="http://schemas.android.com/apk/res/cn.zzm.toolbar" androidrientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <cn.zzm.toolbar.ToolBar android:id="@+id/gridview_toolbar" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:background="@drawable/control_bar" android:gravity="center" toolbar:buttonNum="5" toolbar:itemBackground="@drawable/control_bar_item_bg"/>
</RelativeLayout>

三、在自定义组件中,可以如下获得xml中定义的值:

TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.ToolBar);
buttonNum = a.getInt(R.styleable.ToolBar_buttonNum, 5);
itemBg = a.getResourceId(R.styleable.ToolBar_itemBackground, -1);
a.recycle();

就这么简单的三步,即可完成对自定义属性的使用。

3.如何使用gradle打jar包

在android studio中则有点困难,其主要的原因是需要掌握gradle命令形式。接下来就直接上干货。

首先,在你需要进行分装jar的模块进行build.gradle文件下进行以下添加:


然后在Terminal中执行gradle makeJar命令,如果提示:gradle命令不可用。那么你需要在你的系统环境变量中进行变量的添加:

找到你的gradle插件路径进行添加,然后再在path属性的末尾进行

“;%GRADLE_HOME%\bin”添加。

然后输入 "gradle -v"或者"gradle -version"都可以.

再次运行gradle makeJar。然后再一长串的编译后在末尾看到

表示创建jar包成功,在build/libs下可以看到。

4.APP进程被系统杀死后,还能不能接收到broadcast?

首先,答案肯定是不能的。自android 3.1开始,系统自动给所有intent添加了FLAG_EXCLUDE_STOPPED_PACKAGES,导致app处于停止状态就不能收到广播。要想处于停止状态的app收到广播,需要添加FLAG_INCLUDE_STOPPED_PACKAGES这个标记。这样的话,停止的app应该是能够收到系统广播了。

5.listview的实现原理及工作原理

这个问题笔者以前没有关注过,下来后仔细查看了一番,ListView这么厉害的原因,其中一部分就是因为RecycleBin缓存机制。RecycleBin缓存机制是写在AbsListView的一个内部类。所以ListView继承于AbsListView,也继承了这股力量。RecycleBin缓存机制的工作原理: 
ListView每当一项子view滑出界面时,RecycleBin会调用addScrapView()方法将这个废弃的子view进行缓存。每当子view滑入界面时,RecycleBin会调用getScrapView()方法获取一个废弃已缓存的view。所以我们再看回Adapter的getView()方法:

@Override
public View getView(int position, View convertView, ViewGroup parent) {   View view;  if (convertView == null) {  view = LayoutInflater.from(context).inflate(resourceId, null);  ······} else {  view = convertView;  }   ······return view;
} 

这个convertView是什么?convertView就是RecycleBin缓存机制调用getScrapView()方法获取废弃已缓存的view。getView()方法中有个判断,if (convertView == null),当convertView为空,也就是没有废弃已缓存的view时,将调用LayoutInflater的inflate()方法加载出来布局view,这个操作是比较耗时的;当convertView不为空时,我们就直接用convertView了,而不需要再次调用LayoutInflater的inflate()方法加载出来布局view。

ListView的工作原理:

View在显示到界面的过程中,会进行两次onMeasure()和onLayout()过程。(如果父视图的子视图的个数为0,就会执行一次。否则就会执行多次。因为开始时父试图中是没有子试图的。但是当你从xml文件中加载子试图或者在java代码中添加子试图时,父试图的状态会发生变化,这个变化会引起onlayout甚至是onmeasure。)

第一次onLayout() : 
ListView在加载子项视图的时候,先判断是否有子元素、RecycleBin缓存机制中是否已经有缓存视图了。由于此时ListView是第一次加载,没有任何视图,RecycleBin中也没有任何的缓存记录,所以ListView就直接进行计算,绘制子view等等一系列操作。

第二次onLayout() : 
到了第二次onLayout()的时候,要注意,因为在有了第一次onLayout()的过程,ListView现在已经加载好了子项视图了。所以当ListView再次判断子元素是否为空时,现在子元素不再等于0了。所以这次会进行下面这些操作: 
1. ListView首先调用RecycleBin缓存机制的fillActiveViews()方法,将第一次onLayout()已经加载好的视图全部缓存到mActiveViews中,然后再detach掉第一次所有加载好的视图。这样就解决了第二次onLayout()再次加载视图的时候,出现数据重复的问题。 
2. 巧妙的是,在接下来加载子项视图的时候,也是先判断RecycleBin缓存机制中的mActiveViews是否为空,但是因为刚才ListView已经把第一次加载好的子视图全部缓存到了mActiveViews中了,所以此时mActiveViwe并不空,接下来就只要把mActiveViews里面的视图全部attach到ListView上,这样ListView中所有子视图又全部显示出来了。

ListView的滑动部分工作原理:

滑动部分的机制是写在AbsListView当中的。那么监听触控事件是在onTouchEvent()方法当中进行的。onTouchEvent()方法内有个switch()条件判断。 
1. 首先当判断到我们的动作是滑动时,就计算出我们触发event事件手指在Y方向上的位移距离。 
2. 根据这个距离计算出view是否滑出了界面之外,如果滑出了界面之外,RecycleBin缓存机制就调用addScrapView()方法将这个View加入到废弃缓存当中,然后再将这个view进行detach掉。因为这个view已经移出界面了,所以没必要为它保存。 
3. 接下来,所有子视图就根据这个距离进行相应的偏移。当发现ListView中最后一个View的底部已经移入了屏幕,或者ListView中第一个View的顶部移入了屏幕时,就会对ListView进行填充。 在填充的时候,ListView先调用RecycleBin缓存机制中的getScrapView()方法来尝试从废弃缓存中获取一个View,如果成功从废弃缓存中取得一个scrapView时,我们就将这个scrapView传入getView()方法中,否则就将null传入getView()方法中。

6.Android中定时器任务的实现方式?

Android中定时执行任务的3种实现方法:

一、采用Handler与线程的sleep(long)方法(不建议使用,Java的实现方式)
二、采用Handler的postDelayed(Runnable, long)方法(最简单的android实现)
三、采用Handler与timer及TimerTask结合的方法(比较多的任务时建议使用)

下面逐一介绍:

一、采用Handle与线程的sleep(long)方法

Handler主要用来处理接受到的消息。这只是最主要的方法,当然Handler里还有其他的方法供实现,有兴趣的可以去查API,这里不过多解释。

1. 定义一个Handler类,用于处理接受到的Message。

Handler handler = new Handler() {  public void handleMessage(Message msg) {  // 要做的事情  super.handleMessage(msg);  }
};  

2. 新建一个实现Runnable接口的线程类,如下:

public class MyThread implements Runnable {  @Override  public void run() {  // TODO Auto-generated method stub  while (true) {  try {  Thread.sleep(10000);// 线程暂停10秒,单位毫秒  Message message = new Message();  message.what = 1;  handler.sendMessage(message);// 发送消息  } catch (InterruptedException e) {  // TODO Auto-generated catch block  e.printStackTrace();  }  }  }
}  

3. 在需要启动线程的地方加入下面语句:

new Thread(new MyThread()).start();  

二、采用Handler的postDelayed(Runnable, long)方法

这个实现比较简单一些。

1. 定义一个Handler类

Handler handler=new Handler();
Runnable runnable=new Runnable() {  @Override  public void run() {  // TODO Auto-generated method stub  //要做的事情  handler.postDelayed(this, 2000);  }
};  

2. 启动计时器

handler.postDelayed(runnable, 2000);//每两秒执行一次runnable.  

3. 停止计时器

handler.removeCallbacks(runnable);   

三、采用Handler与timer及TimerTask结合的方法

1. 定义定时器、定时器任务及Handler句柄

private final Timer timer = new Timer();
private TimerTask task;
Handler handler = new Handler() {  @Override  public void handleMessage(Message msg) {  // TODO Auto-generated method stub  // 要做的事情  super.handleMessage(msg);  }
};  

2. 初始化计时器任务

task = new TimerTask() {  @Override  public void run() {  // TODO Auto-generated method stub  Message message = new Message();  message.what = 1;  handler.sendMessage(message);  }
}; 

3. 启动定时器

timer.schedule(task, 2000, 2000);  
schedule(TimerTask task, long delay, long period):这个方法是说,delay/2000秒后执行task, 然后进过period/2000秒再次执行task,这个用于循环任务,执行无数次

4.停止计时器

timer.cancel();  

在写作本篇博客的时候,借鉴了很多同行的博客,在此感谢攻城狮Song,阮一峰,Utopia_Sen,fancsxx等

我是kris,See you next time!!!

Android Studio中gradle命令指定打jar包...(攻城狮Song)

MVC,MVP 和 MVVM 的图示  (阮一峰)
解析Android ListView工作原理及其缓存机制 (Utopia_Sen)
Android中定时执行任务的3种实现方法    (fancsxx)

Android面试题详细整理系列(二)相关推荐

  1. Android面试题详细整理系列(三)

    以下这些面试题都是笔者在(2017年2月-2017年3月)这段时间所面试Android工程师的总结而来,面试的公司包括巨头xx等,还有新贵公司如dd在线科技,gg金融,zk网,momo科技,zbj等, ...

  2. Android面试题详细整理系列(一)

    以下这些面试题都是笔者在(2017年1月-2017年3月)这段时间所面试android工程师的总结而来,面试的公司包括巨头xx等,还有新贵公司如dd在线科技,gm金融,zk网,momo科技,zbj等, ...

  3. 我自己的Android面试试题总结整理

    http://blog.sina.com.cn/s/blog_ad991b1601018mjc.html 2013-5-9号补充:今天最新的腾讯面试题,应该说是所有面试中最难的,我个人感觉.而且是个女 ...

  4. android蓝牙设置特征属性,Android BLE蓝牙详细解读(二)

    上篇文章主要介绍了关于BLE的一些基础操作,我们能够大概了解到蓝牙操作的一些流程,上文末介绍了本人的一个BLE开源库,支持蓝牙一对多的连接方式,该库封装了蓝牙的开启.扫描.连接.断开.连接超时...一 ...

  5. Android面试题最新整理,2022年最新版

    每年的9月和10月 是互联网大厂疯狂招人的时期 也是程序员们跳槽的黄金期 不知道你有没有幻想过这样一个场景: 大厂的面试官说 恭喜你通过面试,明天来办理入职吧! 今天,为大家整理了2022年Andro ...

  6. android面试题-人事面试宝典二

    人事面试宝典一 为什么要离职? 回答提示: ①回答这个问题时一定要小心,就算在前一个工作受到再大的委屈,对公司有多少的怨言,都千万不要表现出来,尤其要避免对公司本身主管的批评,避免面试官的负面情绪及印 ...

  7. ionic2 mac android,Ionic制作Hybrid App系列二:Mac环境下Ionic release版本APK的签名与发布...

    Android应用程序签名 在前一章节里面,通过ionic run使app成功在手机上面跑起来,并且将android-debug.apk放到手机上后发现也能正常的安装,debug版本和release版 ...

  8. Android面试题总结加强版(二)

    http://blog.csdn.net/superjunjin/article/details/7855995 16.Android常用控件的信息 单选框(RadioButton与RadioGrou ...

  9. Android 面试题集整理

    1.RecycleView的缓存复用机制 https://mbd.baidu.com/ma/s/WEDpFTTo https://blog.csdn.net/m0_37796683/article/d ...

最新文章

  1. STM32固件库文件树及构成详解
  2. 怎么连接屏幕_触控一体机怎么实现无线投屏功能
  3. Linux(二)——基础入门(2)
  4. 在服务器上使用第三方独立组件对Word/Excel进行编程
  5. 关于ubantu软件包的相关记录
  6. Linux内核Crash分析
  7. LeetCode 2104. 子数组范围和(单调栈)
  8. Windows自带渗透工具Certutil介绍(免杀、哈希计算、md5、sha256、下载文件、base64编码)
  9. 文献阅读 | Epigenetics in ENS development and Hirschsprung disease
  10. 每位初级开发都应该知道的六件大事
  11. COLING2018计算语言学进展
  12. c语言九九乘法表的值,c语言九九乘法表!
  13. pads layout 无法将dxf文件导入进来的2D Line转换成Board Outline
  14. vscode最适合编程的 6 种字体
  15. 【JZOJ】立体井字棋
  16. 第一章 C语言郝斌笔记
  17. 【懒懒】我不生产笑话,我只是笑话的搬运工 [问题点数:200分]
  18. 深入了解前端路由 hash 与 history 差异
  19. matlab中的textscan函数
  20. ABAP 新特性 - COND SWITCH 操作符

热门文章

  1. 需要掌握的八个CSS布局技巧
  2. Go web 编程资源
  3. leetcode刷题实录:1
  4. 编程方法学17:多维数组
  5. 二十万字C/C++、嵌入式软开面试题全集宝典八
  6. [云炬创业基础笔记]第五章创业计划评估17
  7. 云炬随笔20211017(1)
  8. 学长毕业日记 :本科毕业论文写成博士论文的神操作20170413
  9. python嵌套字典代码_python – 尝试在嵌套字典中查找唯一值的总和. (见例子!)
  10. Siamese Network (应用篇2) :孪生网络用于图像块匹配 CVPR2015