v:* {behavior:url(#default#VML);} o:* {behavior:url(#default#VML);} w:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);}javascript
Normaljava
0android
falsegit
7.8 磅程序员
0github
2web
false面试
false正则表达式
false算法
EN-US
ZH-CN
X-NONE
/* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:等线; mso-ascii-font-family:等线; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:等线; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:等线; mso-hansi-theme-font:minor-latin; mso-font-kerning:1.0pt;} table.MsoTableGrid {mso-style-name:网格型; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-priority:39; mso-style-unhide:no; border:solid windowtext 1.0pt; mso-border-alt:solid windowtext .5pt; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-border-insideh:.5pt solid windowtext; mso-border-insidev:.5pt solid windowtext; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:等线; mso-ascii-font-family:等线; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:等线; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:等线; mso-hansi-theme-font:minor-latin; mso-font-kerning:1.0pt;}
Android技术面(注意时间的把握与控制) **
1**、自我介绍一下吧(一两分钟内,简短介绍学习、项目经历) **
我是来自广东工业大学信息工程学院的吴焕楠,面目一新的焕,木字边加东南西北的楠,我来应聘的岗位是android开发工程师。大二开始自学android开发,看的是淘宝网买的一套黑马程序员的视频教程,后来又在菜鸟窝官网学习了一套叫作《菜鸟商城》的实战视频教程,后期主要是靠实习和看书,看博客来提高本身的技术水平。
2**、在什么地方实习过?实习多久?平时主要作什么?离职了吗?为何离职? **
是这样的,我是在今年3月份开始在悦乎网络科技有限公司实习的,一直到九月份才离职,一共工做了6个月。这家公司是一家创业型公司,规模比较小,可是基本全部功能模块都是本身独立完成的,这样能够有更多锻炼本身的机会。可是毕竟是实习,薪水只能知足于生活费用,如今以为本身的水平已经有必定提高,所以想获得贵公司的承认。
平时主要的任务就是负责开发《师兄帮帮》APP的各类功能模块的调研,开发以及平常的升级与维护。
3**、能不能简单介绍一下你作过的APP?开发周期?你作的项目,说一下优缺点,有什么想改进的地方? **
《师兄帮帮》是一款垂直社交应用平台,这款产品主打是大学生,里面有20万份资料供用户阅读查看和下载。用户能够在这个平台上发布问题或者须要,也能够进行抢单,解决问题之后就有相应的报酬。
**开发周期:**一个星期一个小版本,一个月一个大版本
优势是:技术方面:在架构设计方面比较混乱,没有用到一些比较新的架构。细节上面:尚未适配android6.0的动态权限。
非技术方面:界面比较清晰易懂,但就是功能过于单一。限制太多,不少功能须要花钱,并且用户之间的互动比较少。至于app的盈利模式,公司规定不能向外透露。
4**、你在开发这个APP的时候你遇到过的技术难点有什么?你是怎么解决的?(重点问题,必定要准备) **
*******注意点: **
1**、说到实现一个功能的时候,先说本身想办法,调研。实在找不到解决方案的时候,就说网上已经有成熟的解决方案。最好能说说找到了什么方案,最好能说一些外国的SDK或者库,给人一种比较牛逼的感受。 **
2**、最好在说的时候突出一下团队合做,突出本身有提早调研过,计划好才开始写代码,实在是按时完成不了的就说本身是另外找时间加班完成的。 **
** **
0、内存泄漏问题
解决:
先介绍内存泄漏:用例子说明,个人手表明app所能使用的内存,手里面可以放不少东西。好比我手里有钥匙,洋娃娃。而洋娃娃须要扬声器才能工做,那么洋娃娃和扬声器之间就有了引用的关系。一旦我扔掉了洋娃娃,就会有垃圾回收器来回收。可是意外的是,个人钥匙和洋娃娃黏在了一块儿,阻止了我扔掉洋娃娃。致使洋娃娃不会被回收掉。内存泄漏就是外部的引用指向了原本应该被回收的对象,形成对象不能被释放,致使了内存泄漏。
项目中,为了app的特效,打算作水波纹效果,可是这是5.0以上原有的,如下版本须要本身手动实现ViewGroup,后来发现了github上面的水波纹效果控件。可是致使app变卡,初步判定是内存泄漏致使的。使用LeakCanary来进行检测内存泄漏(结合Demo),最终分析出是BitMap对象没有recycle致使。Demo分析,静态变量比较特殊,是GC root的一种,回收器只会回收非GC root的对象。解决办法:手动设置为null,或者使用弱引用。
LeakCanary检测内存泄漏的原理是利用虚引用(虚引用不会影响回收,即虚引用不会对象的生命周期,回收取决于对象是否还存在强引用)对被测对象打一个标记,当对象回调销毁(onDestory)以后,一旦判断到这个弱引用还存在的话,就说明对象不能被正确回收,形成了内存泄漏。而后利用API把堆内存的信息dump出来,而且弹出通知提醒用户,最终把信息显示到界面上面。
一、
APP内部查阅资料的问题:资料有word、excel、ppt、PDF、图片等格式。因为PDF和大图的查看网上有不少成熟的解决方案。可是谷歌官方并无在android原平生台查看office文档的功能,相对来讲IOS的浏览器内核Safari是支持直接打开office文档的。
解决:原本打算本身实现,可是发现工做量很大,所以只能找第三方解决方案。当时考虑过使用Apache的POI,可是发现这个库主要是java方向的,对于android的兼容性作得不是很好,引入的时候出现过不少问题。也考虑过使用韩国的一款office SDK,叫作北极星Office,可是后来考虑到这个SDK收费太贵因此没有使用。最后是决定采用使用Web Office服务,有服务动态生成office文档的url,用android的WebView来加载和浏览。
二、
第二个要说的就是沉浸式状态栏的实现。这个问题比较尴尬,由于咱们的标题栏是白色的,所以若是直接设置状态栏的颜色为白色的话,那么原有的状态栏上面的文字是白色的话就看不见了。
解决:目前来讲只有小米、魅族以及android6.0以上才提供了设置状态栏字体颜色的API。考虑到兼容性问题,只能参考市面上的一些app,把状态栏设置为半透明的黑色。使用了github上面的一个开源库system bar tint,而且在app主题中开启了透明状态栏。
三、
短信验证码的自动填写。
解决:使用Content Observer去观察短信数据库的收件箱,当有新的短信进来的时候,就经过正则表达式去获取短信中的验证码,而且经过handler把结果传递到UI中。四个连续数字(\d{4})
四、
动态库文件(so文件)冲突:因为当时想引入Fresco图片缓存框架,可是后来发现因为Fresco框架对不一样架构的平台的支持得很是好,提供了全部平台的so包,可是这样会致使app不能正确加载其余库(如短信验证SDK)的so库,从而引起crash。
解决:当时是看到Stack Overflow上的一篇博客介绍,经过配置APP的gradle脚本文件,使得app只输出armabi架构的so包,成功解决问题。
五、
实现防止多终端登陆同一个帐号的时候,服务器须要知道用户是否正在登陆app。
解决:经过后台开一个Service,每隔一段时间去访问服务端的一个心跳接口,从而告诉服务端app的某个帐号正在使用。当时也考虑过其余的解决方案,可是这个惟有客户端去轮询才能实现。
六、
使用第三方SDK时,例如融云即便聊天、Ping++的时候,遇到问题通常都是经过提交工单的方式去寻求解决。
5**、你说你看过好多书,能不能简单介绍一下你看过什么书?平时看什么博客?本身写过博客吗? **
《android源码设计模式解析与实战》,这是一本介绍了设计原则、设计模式以及android源码的一本书。
《android群英传》,《android开发艺术探索》,《android开发从小工到专家》,这些都是android方面的技术进阶书籍,从各个方面介绍android开发中的一些常见的难点。
《android神兵利器》,主要介绍了git、android studio等工具的使用,还没看完。
平时看的博客主要来源于CSDN,微信公众号等,本身有在简书上面写技术博客以及笔记。
6**、你会不会使用反射技术?你是怎么理解这个技术的?在什么地方用过? **
我对反射技术的理解就是,反射就是把Java类中的各类成分经过java的反射API映射成相应的Java类,获得这些类之后就能够对其进行使用。好比方法,构造方法,成员变量,类型,包等。
直接用到反射技术的很少,通常都是间接用到比较多。好比:
一、android中的经过读取布局文件的信息,而后利用反射来构造各类控件的对象。
二、使用开源ORM数据库框架的时候,是经过反射的方式来进行java Bean和表的映射的。
三、Gson在解析JSON而且生成Bean对象的时候利用了反射技术。
7**、什么是设计模式?你知道哪些设计模式?简单介绍一下吧 **
设计模式(Design pattern)是一套被反复使用、多数人知晓的、通过分类编目的、代码设计经验的总结。
单例模式,主要用在一些资源消耗比较多的类身上,比较典型的实现由DCL方式、枚举、静态内部类来实现。例子有
单例模式的DCL失效问题:虚拟机容许指令的乱序执行,当单例实例化的时候,实际上会执行了三个步骤:
给单例实例分配内存空间
调用单例实例的构造函数,初始化一些字段
将单例实例对象指向分配的内存空间(sInstance不为null)
二、3两步的执行顺序是不肯定的,所以若是在多线程的状态下,线程A执行了3之后,线程B立刻来取走实例,就是报错(由于第二部的初始化尚未完成)
Builder模式,主要是用做一些复杂类的构建,而且通常支持连点操做。例子:
Adapter模式:这种模式主要是解决接口不兼容的问题。例子:
咱们经常使用的ListView、RecycleView等,就使用了adapter模式设计,这样作分离了ListView显示视图,Adapter提供数据以及操做的功能,负责单一职责原则。
观察者模式:这种模式是主要有被观察者、观察者组成,当被观察者的观察行为发上变化的时候,观察者能够立刻作出相应处理。例子:
Content Observer
RXJava
ListView、RecycleView在设置Adapter的时候也注册了数据观察者,当用户调用notifyDateSetChange等方法的时候,这些观察者就会通知这些控件去从新刷新视图。
工厂模式:主要是定义了一个对象建立的接口,具体产生什么类由用户去实现。例子:
装饰者模式:动态地给一个对象添加一些额外的功能。例子:应用:IO流,ContextWrapper等。
8**、Java与JS的交互**
一、Java调用JS:直接利用WebView加载URL便可:webview.loadUrl("javascript:method("+参数+")");
二、WebView设置使能JS,建立JS Interface,设置到WebView当中。JS经过中window.appInterface.buy(id);调用Java方法。
9**、简述一下android的消息传递机制吧。 **
Android中的消息机制主要是指Handler的运行机制。Handler是进行线程切换的关键,在主线程和子线程之间切换只是一种比较特殊的使用情景而已。其中消息传递机制须要了解的东西有Message、Handler、Looper、Looper里面的MessageQueue对象。咱们能够把整个消息机制看做是一条流水线。其中:
app在启动的时候,也就是执行ActivityThread的main方法的时候,会为主线程建立Looper,而且启动整个app的消息循环,同时保证app不会立马退出。
另外,子线程之间也能够利用Handler进行通讯,甚至是子线程能够经过Handler发消息给主线程。前提条件是子线程没有关联Looper,所以必须手动建立Looper而且启动消息循环。
10**、简述一下android的事件传递机制吧。遇到过(滑动)事件冲突吗?你是怎么解决的? **
事件老是从上往下进行分发,即先到达Activity,再到达ViewGroup,再到达子View,若是没有任何成员消耗事件的话,事件会顺着路径往回传递。
遇到过事件冲突:就是ViewPager其中一个Pager上面的Banner,当Banner还没滑到最后一页的时候,应该请求ViewPager不要拦截本身的滑动事件;当Banner滑动到最后一页的时候,要请求ViewPager去拦截本身的滑动事件,从而使得ViewPager可以跟Banner配合工做。
结合本身的Demo说说,举例子:爷父子之间传递苹果
11**、简要说说View的工做机制。有自定义过View吗?简要说说。 **
View的工做机制(View的绘制流程)主要包括测量(Measure)和绘制(Draw),而对于ViewGroup来讲还包括布局(Layout)。
一、测量主要是根据用户指定的测量大小以及模式经过setMeasuredDimension方法去设置View的大小。精确模式下须要返回用户指定的大小。最大值模式以及不明确指定的模式下,须要提供默认大小,在最大值模式下须要返回二者的最小值。
二、绘制主要是经过一些画图API好比画布画笔,在View区域上面动态画一些东西。
三、布局主要是自定义ViewGroup的时候实现的,主要是控制各个子View在ViewGroup的位置以及他们之间的位置关系。
把《师兄帮帮》那个录音按钮给面试官看
12**、有没有(参与)写过(开源)框架? **
虽然我没有在GitHub上面参与或者发表过开源项目,感受本身想传上去,可是发现已经有实现了,可是我常常关注GitHub上面看一些不错的开源项目和控件,好比说BGARefreshLayout、BaseRecyclerViewAdapterHelper、代码家以及各类自定义控件等。日常也有关注一些android开发相关的微信公众号,好比徐宜生、郭霖、android开发技术前线等,以及简书、CSDN等一些大牛的博客,平时本身也有在简书上面用MD来写一些技术文章。
13**、有没有关注一些新技术? **
RXJava:
一个异步请求库,核心就是异步。利用的是一种扩展的观察模式,被观察者发生某种变化的时候,能够经过事件(onNext、onError、onComplete)等方式经过观察者。RXJava同时支持线程的调度和切换,用户能够指定订阅发生的线程以及观察者触发的线程。
Retrofit 2.0:
经过注解的方式来指定URL、请求方法,实质上底层是经过OKHttp来实现的。
Dagger 2:一个依赖注入框架
HotFit:淘宝的Dexposed(兼容性很差,利用AOP面向切面编程实现)、阿里巴巴的AndFix(Dexposed从Method入手,可是AndFix从Field入手,不须要重启),QQ空间的ClassLoader(虚拟机加载类以前,经过反射去修复有问题的Dex文件),微信的Tinker(没有了解过,由于以前的手机用不了)、Nuwa(须要重启)
插件式开发:核心是动态加载技术。当app愈来愈大的时候,经过插件化来减轻应用的内存以及CPU,还能够实现热插拔,实现动态修复和更新。
大概了解,须要用到的技术:反射、动态代理、类加载器原理等。插件开发是开发者经过将插件代码封装成Jar或者Apk文件放在网络或者本地。在宿主app中加载而且调用插件中的方法。
14**、看过什么框架?源码?原理?有没有本身写过框架? **
**网络请求框架的基本流程: **
一、首先build request参数
二、由于不能在主线程请求HTTP,因此你得有个Executor或者线程
三、enqueue后,经过线程去执行请求,把Request对象经过字节流输出
四、获得服务器数据后,获取返回的输入字节流,经过反序列化转换成需
要的实体对象,最后经过callback回调给客户端,同时还要实现线程切换
**Retrofit****的一些优势: **
一、类型安全:经过指定泛型来实现
二、可扩展性强,能够适应不一样的业务需求
三、简洁高效:经过注解的方式来实现网络请求,大大减小了代码量
四、高度解耦,内部经过Adapter模式适配不一样的框架,好比RXJava等
**Retrofit****源码流程概述: **
一、先经过Builder模式去构造Retrofit对象,其中Retrofit只是外观模式包装的一个对象,全部基本功能都经过Retrofit来对外提供。构造Retrofit的内部构造了OkHttpClient对象,而且构建了CallbackExecutor对象,用来处理请求。同时也为Retrofit指定了Converter。
二、为咱们的请求接口建立动态代理对象,当这个对象的方法被调用的时候,会被拦截,而且经过ServiceMethod类去经过反射的方式去获取这个对象上面的注解,经过这些注解获取网络请求方法、请求体等,最后构造出OKHttpCall对象、RequestConverter以及ResponseConverter,这两个Converter分别是表明把请求对象、返回对象进行转换,例如转换成JSON、XML等。(注意:因为经过反射获取对象的注解是耗时而且消耗性能的,ServiceMethod内部有作缓存,解析过就直接复用)
三、当咱们调用Call对象进行enqueue或者execute的时候,内部是把OKHttpCall转换成CallAdapter,分别适配:RxJava, Java8, Guava还有一个Retrofit默认的回调。
四、把请求分发给CallbackExecutor对象执行,CallbackExecutor内部实际上是调用OkHttp的一些相关方法进行请求。请求执行的时候经过RequestConverter进行转换。
五、请求返回的时候,判断返回码的类型,经过ResponseConverter对象把返回的字节流转换成实体对象,最后经过Handler机制post一个Runnable把Callback回调给主线程,刷新界面等操做。若是是使用RXJava的话,还能够很方便地先去指定子线程进行数据转换再返回主线程进行界面刷新。
**Retrofit****的一些功能扩展: **
一、经过自定义RequestConverter以及ResponseConverter进行数据网络传输的加密、解密。
二、能够经过自定义线程池来维护请求队列,适应具体的业务需求。好比先进先出、后进先出等。
三、经过Adapter模式(CallbackAdapter)能够利用不一样的框架实现不一样的回调代码,好比RXJava、Java八、Guava等。
四、经过不一样Converter实现Request以及Resource适应不一样的协议,好比JSON、XML等。
主流的网络请求框架
1**、**HttpURLConnection:在android4.4中已经替换成OKHttp了。
2**、**HttpClient:API数量比较多,使得咱们很难在不破坏兼容性的
状况下对它进行升级和扩展维护成本较高,android5.0废弃,6.0删除。
3**、**Volley:已经中止更新。Android2.2如下版本使用HttpClient、
android2.2以上版本使用HttpURLConnection实现。可是相对来讲扩
展性比Okhttp较低。
4**、**OkHttp:支持自定义请求头、支持通常的请求方法、文件上传
下载、图片加载、IP自动重连、Gzip、SPDY、链接池、HTTP缓存等。
Retrofit:和Volley框架的请求方式很类似,底层网络请求采用okhttp
(效率高,android4.4底层采用okhttp),采用注解方式来指定请求方
式和url地址,减小了代码量。
主流的图片加载框架
1.、Picasso:和Square的网络库一块儿能发挥最大做用,由于Picasso能够选择将网络请求的缓存部分交给了okhttp实现。 2.、Glide:模仿了Picasso的API,并且在他的基础上加了不少的扩展(好比gif等支持),支持图片流,所以在作爱拍之类的视频应用用得比较多一些。 3.、Fresco:Fresco中设计有一个叫作image pipeline的模块。它负责从网络,从本地文件系统,本地资源加载图片。 为了最大限度节省空间和CPU时间,它含有3级缓存设计(2级内存,1级文件)。Fresco中设计有一个叫作Drawees模块, 方便地显示loading图,当图片再也不显示在屏幕上时,及时地释放内存和空间占用。
Fresco是把图片缓存放在了Ashmem(系统匿名内存共享区)
无论发生什么,垃圾回收器都不会自动回收这些 Bitmap。当 Android 绘制系统在渲染这些图片,Android 的系统库就会把这些Bitmap 从 Ashmem 堆中抽取出来,而当渲染结束后,这些Bitmap 又会被放回到原来的位置。若是一个被抽取的图片须要再绘制一次,系统仅仅须要把它再解码一次,这个操做很是迅速。
图片的三级缓存
当app须要使用图片的时候,先到内存缓存去取,由于内存缓存速度最快。若是内存缓存没有,再去本地缓存取,若是都没有,就到网络获取。获取之后分别写入内存缓存以及本地缓存。
本身写过图片加载框架:
概述:利用组合设计模式,图片加载功能在ImageLoader集中对外公开,ImageLoader是统筹了图片下载器,图片缓存等功能。
ImageLoader
ImageDownloaderer
ImageCache
ImageLoader
ImageLoader
遇到的问题:
一、
使用LruCache代替弱(软)引用存储,由于API9之后GC会更倾向于回收持有弱引用的对象。LruCache是android提供的一个缓存工具类,其算法是最近最少使用算法。它把最近使用的对象用“强引用”存储在LinkedHashMap中,而且把最近最少使用的对象在缓存值达到预设定值以前就从内存中移除。其在API12被引进,低版本能够用support包中的类。
二、
图片的错位问题。经过给ImageView打一个url标记,每次设置显示图片的时候先判断Bitmap是否对应某一个ImageView。
三、
url做为键值对中的键问题,使用MD5算法把url转为MD5字符串。
15**、网络优化、网络安全问题。**
为何要作缓存,或者说有什么好处?
一、减小服务器负荷,下降延迟提高用户体验。
二、复杂的缓存策略会根据用户当前的网络状况采起不一样的缓存策略,好比在2g网络不好的状况下,提升缓存使用的时间;
三、不用的应用、业务需求、接口所须要的缓存策略也会不同,有的要保证数据的实时性,因此不能有缓存,有的你能够缓存5分钟,等等。你要根据具体状况所需数据的时效性状况给出不一样的方案。固然你也能够所有都同样的缓存策略,看你本身。
网络优化建议点:
一、链接复用节省链接创建时间,如开启keep-alive
二、不用域名,用IP直连省去DNS解析过程,根据域名获得IP地址
三、可以缓存的尽可能缓存起来,减小网络请求,减轻服务器负担
网络请求的安全性问题: 这块了解的很少。我给你说说个人思路吧,利用对称加密。服务器给咱们的数据能够经过密钥和其余参数作个MD5加密,获得一个key;在客户端按照相同的办法生成key而后与服务端给的作个对比。
对称加密: 文件加密和解密使用相同的密钥,即加密密钥也能够用做解密密钥。DES、IDEA
非对称加密: 非对称加密算法须要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,若是用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;若是用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。RSA,RCC
16**、进程、线程通讯、Linux相关 **
如何开启多进程?
一、经过在清单文件对四大组件指定android:process属性。除此以外android是没有办法指定线程或者实体类运行所在的进程。
二、很是规方法:经过JNI在native层去fork一个新的进程。
多进程所带来的问题: 一、静态成员和单例模式彻底失效。
二、线程同步机制会彻底失效。
三、SharePreferences的可靠性会降低。 四、Application会屡次被建立,例如在推送或者即时通讯SDK中,须要单独开一个进程来接收消息,那么咱们在Application中初始化SDK的时候,须要判断当前进程是否为当前APP的主进程,是就初始化,不然不作任何操做。
进程间通讯方式对比:
方式
优势
缺点
适用场景
Bundle
简单易用
只支持Bundle支持的数据类型
四大组件之间的跨进程通讯
文件共享
简单易用
不适合高并发场景,而且没法作到即时通讯
无并发的情形,实时性不高的场景
AIDL
功能强大,支持一对多并发实时通讯
适用稍微复杂,须要处理线程同步问题
一对多通讯,实时性高
Messenger
功能通常,支持一对多串行实时通讯
不能很好处理高并发,只能传输Bundle支持的类型
低并发的一对多实时通讯,无需返回结果
ContentProvider
数据源访问方面功能强大,支持一对多并发数据共享,能够经过call方法进行扩展
能够理解为受约束的AIDL,主要是数据源提供CRUD操纵
一对多的进程间数据共享
Socket
功能强大,经过网络传输字节流,支持一对多并发实时通讯
实现麻烦,不支持直接的RPC
网络数据交换
**Linux****中的进程间通讯方式: **
一、命名管道 二、共享内存 三、信号量
**Android****中进程的级别: **
前台进程(正在与用户交互)、可见进程(有可见的界面)、服务进程、后台进程、空进程
经常使用的Linux命令:mkdir 建立文件夹、rmdir 删除文件夹、rm 删除文件、mv 移动文件、cp 拷贝文件、cat 查看文件
tail 查看文件尾部、more 分页查看文件、cd 切换当前目录、ls 列出文件清单、reboot 重启、date 显示日期
cal 显示日历、ps 查看系统进程至关于windows 的任务管理器、ifconfig 配置网络
** **
**Linux****进程和DVM的进程是否为同一个概念? **
每个Android 应用程序都拥有一个独立的虚拟机实例,应用程序都在它本身的进程中运行。而每个dvm都是在Linux中的一个进程,因此说能够近似认为是同一个概念。
独立的进程能够防止在虚拟机崩溃的时候全部程序都被关闭。
**Android****中的安全机制 **
一、Android 是基于Linux 内核的,所以Linux 对文件权限的控制一样适用于Android。在Android 中每一个应用都有本身的/data/data/包名文件夹,该文件夹只能该应用访问,而其余应用则无权访问。
二、Android 的权限机制保护了用户的合法权益。如咱们的代码想拨打电话、发送短信、访问通讯录、定位、访问sdcard等全部可能侵犯用于权益的行为都是必需要在AndroidManifest.xml 中进行声明的,这样就给了用户一个知情权。而且在android6.0中引入了动态权限管理
三、Android 的代码混淆以及apk的签名保护了开发者的权益。
**AIDL****主要思路(步骤)就是: **
一、服务端建立一个Service来监听客户端的链接请求。建立AIDL文件,将接口暴露给客户端,并在Service中实现这个接口。
二、客户端绑定Service,并定成功以后将服务端返回的Binder对象转换成AIDL中的接口类型,而后就能够调用接口的方法,而且获取返回值。
17**、Android新特性相关**
18、在技术上的发展有什么规划?(离职缘由)(实现本身的价值,学习牛逼的技术,公司的发展前景) **
以前的公司就是直接实现业务逻辑的,功能的话只要给时间必定能够实现的。而后在上一家公司就是接触到了一些思想层次上的,好比设计模式啊MVC之类的,而后买了一些书来看,如今在往这方面发展。之后的就要等我再学到必定层次再考虑了。
19、屏幕适配 **
1、**对应不一样屏幕建立不一样的dimen的文件夹,放置不一样的大小 ,根据屏幕分辨率建立不一样layout文件夹,使用权重来适配
2、**使用九切图和SVG图片、xml来代替直接使用png
3、长度单位用dp代替px ** 4**、使用wrap_content, match_parent, weight 5、**使用相对布局,在开发中禁用绝对布局
**上和左控制拉伸,下和右负责内容区域 五、使用线性布局,放不下的时候用ScrollView包裹 **
20**、android分包、插件化、热修复等相关知识: **
Dex分包 **
**引入缘由:**在apk代码量愈来愈多的时候,每每会出现方法数量过多(超过了65536),而一个dex文件最多只支持65536个方法;apk过大不能在一些旧版本的android手机上面安装,由于android2.3之前的版本分配 用来执行dex优化的 内存只有5M。
android的加载器体系与java类加载器体系对比: **
一、PathClassLoader:加载安卓应用,只能加载
已安装到系统中(即/data/app目录下)的
apk文件。
二、 DexClass:能够加载apk,jar,及dex文件。
加载一个类的时候,ClassLoader先遍历一个装在dex文件(每一个dex文件其实是一个DexFile对象)的数组(Element数组,Element是一个内部类),而后依次去加载所须要的class文件,直到找到为止。
Dex注入的解决方案:假如咱们将第二个dex文件放入Element数组中,在加载第二个dex包中的类时,应该能够直接找到。 **
Dex分包的注意要点: **
因为第二个dex包是在Application的onCreate中动态注入的,若是dex包过大,会使app(Activity)的启动速度变慢,所以,在dex分包过程当中必定要注意,第二个dex包不宜过大。
因为上述第一点的限制,假如咱们的app愈来愈臃肿和庞大,每每会采起dex分包方案和插件化方案配合使用,将一些非核心独立功能作成插件加载,核心功能再分包加载。
** **
**插件化 **
思路:经过在宿主app里面注册添加一些activity做为插件app的容器,加载插件app,经过动态代理的方法去处理被
加载(被代理)的activity、fragment的生命周期。由此引出Activity与Fragment之间的传值问题**
第三方服务:apkplug,尚未仔细研究就辞职了,由此引出久邦数码举办的app创新设计大赛。
插件化第三方框架:360的DroidPlugin、携程的DynamicAPK、今年初开源的Small
21**、android插件化是否有其余更好的代替方法? **
**插件化引入: **
一、APK方法数量过多二、低版本手机安装出错
三、移动应用中的2/8定律,80%的用户访问20%的页面,那么剩下80%的页面是不必用户去下载的,只有在用到的时候去下载。经过这样能够大大减轻app对CPU、内存的负担,同时也实现动态加载的目的。
**代替方案: **
一、移动应用从C/S架构向B/S架构的转变。最近比较火的一个框架React Native。基于页面级别的动态加载。二、买付费的Proguard
三、最笨的方法是删除无用的代码以及模块
**热修复 **
app上线以后须要紧急去修改一些有问题的代码,常规的方法是从新测试、打包、混淆加密加固、上线。这样太麻烦。
**第三方方案: **
**阿里巴巴的AndFix:**经过加载器读取一个dex文件中的类,并找到被注解标记到的要修复的方法,再经过jni在C层替换掉本来出BUG的方法的指针,从而达到热修复的目的。
QQ空间的热修复方案:**MultiDex的思路,在应用启动的时候,往Classloader的PathList里面插入一个Dex,经过覆盖掉出BUG的类来作到热修复。QQ空间只出了理论方案,而这套方案的开源代码实现,则是由 贾吉鑫 写了一个 nuwa 托管在 Github 上。
** **
22**、怎么定位 **
**anr****问题代码位置? **
** **
ANR:**Application Not Response
致使ANR的缘由有:主线程(Activity、Service)是5 秒,BroadCastReceiver 是10 秒。(本身项目:在主线程去读取SD卡)
**解决方案:**将全部耗时操做,好比访问网络,Socket 通讯,查询大量SQL 语句,复杂逻辑计算等都放在子线程中去,而后经过handler.sendMessage、runonUITread去刷新UI;显示Loading!!!;onReceive启动Service
**定位:**发生ANR之后,系统会在/data/anr目录下面生成一个traces.txt文件
第一步,先pull出/data/anr/traces.txt文件。 第二步,查看app被杀死时的线程id。 第三步,查看traces.txt里关于该线程id的信息。
典型场景,调用关系比较复杂的时候,好比说主线程的方法里面开了一个子线程,子线程得到了同步锁,主线程的方法被阻塞掉。此时应该先分析主线程,查看什么锁被什么线程hold住了,而后再对应去看那个线程。
23**、避免OOM的一些常见方法:**
一、App资源中尽可能少用大图。使用Bitmap的时候要注意等比例缩小图片,而且注意Bitmap的回收。 BitmapFactory.Options options = new BitmapFactory.Option(); options.inSampleSize = 2; //Options 只保存图片尺寸大小,不保存图片到内存 BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inSampleSize = 2; Bitmap bmp = null; bmp = BitmapFactory.decodeResource(getResources(), mImageIds[position],opts); //回收 bmp.recycle(); 二、结合组件的生命周期,释放资源 三、IO流,数据库查询的游标等应该在使用完以后及时关闭。 四、ListView中应该使用ViewHolder模式缓存ConverView 五、页面切换的时候尽可能去传递(复用)一些对象,经过Intent传递过去
24**、Android中如何捕获未捕获的异常 **
一、自定义Application,实现Thread.UncaughtExceptionHandler
二、实现uncaughtException(Thread t, Throwable e)方法,在方法中处理异常。若是不能处理的话,通常android.os.Process.killProcess(android.os.Process.myPid());来结束本身,避免把异常信息报给用户。
三、在Application初始化的时候设置Thread.setDefaultUncaughtExceptionHandler(this);
** **
25**、Android6.0新增的动态权限 **
一、对于6.0如下的权限及在安装的时候,根据权限声明产生一个权限列表,用户只有在赞成以后才能完成app的安装,也就是说权限在安装的时候已经授予了。
二、对于6.0或以上的版本,谷歌把权限分为了两类,
一种是Normal Permission,例如访问网络、网络状态获取、震动等;
另一种是Dangerous Permission,例如发送、读取短信、打电话、读取通讯录、录音等。而且引入了权限组的概念,若是你申请某个危险的权限,假设你的app早已被用户受权了同一组的某个危险权限,那么系统会当即受权,而不须要用户去点击受权
**权限申请方式: **
一、在清单文件里面配置权限,跟之前同样。
二、检查权限ContextCompat.checkSelfPermission,方法返回值为PackageManager.PERMISSION_DENIED或者PackageManager.PERMISSION_GRANTED。
三、在Activity中使用ActivityCompat的requestPermissions,或者在Fragment里面直接使用Fragment提供的requestPermissions方法去申请某一个危险权限,而后在onRequestPermissionsResult回调里面进行业务逻辑。
**最简单的解决方式:在gradle配置文件中把targetSDK改成小于23。 **
26**、布局优化 **
一、使用includea标签去复用相同的布局
二、使用merge标签去除同类的视图
三、使用ViewStub来延迟加载一些不经常使用的布局
27**、内存优化 **
一、珍惜Service资源,尽可能使用IntentService IntentService在内部实际上是经过线程以及Handler实现的,当有新的Intent到来的时候,会建立线程而且处理这个Intent,处理完毕之后就自动销毁自身。所以使用IntentService可以节省系统资源。
二、实现一些在内存紧张的时候会回调的一些方法,好比Activity中的onLowMemory、onTrimMemory。好比中止动画特效等。
三、经过Manifest中对Application配置更大的内存,可是通常不推荐。 android:largeHeap="true" 四、避免Bitmap的浪费,应该尽可能去适配屏幕设备。尽可能使用成熟的图片加载框架,Picasso,Fresco,Glide等。 五、使用优化的容器,SparseArray等 六、其余建议:尽可能少用枚举变量,尽可能少用抽象,尽可能少增长类,避免使用依赖注入框架,谨慎使用library,使用代码混淆,时当场合考虑使用多进程等。 七、避免内存泄漏(原本应该被回收的对象没有被回收)。一旦APP的内存短期内快速增加或者GC很是频繁的时候,就应该考虑是不是内存泄漏致使的。
28**、性能优化 **
一、防止过分绘制,经过打开手机的“显示过分绘制区域”便可查看过分绘制的状况。 二、最小化渲染时间,使用视图树查看节点,对节点进行性能分析。 3经过TraceView进行数据的采集以及分析。在有大概定位的时候,使用Android官方提供的Debug类进行采集。最后经过DDMS便可打开这个.trace文件,分析函数的调用状况(包括在指定状况下执行时间,调用次数) //开启数据采集 Debug.startMethodTracing("test.trace"); //关闭 Debug.stopMethodTracing();
29**、SharedPreference **
SharedPreference.Editor的apply和commit方法异同: ** 1. apply没有返回值而commit返回boolean代表修改是否提交成功 2. apply是将修改数据原子提交到内存, 然后异步真正提交到硬件磁盘, 而commit是同步的提交到硬件磁盘,所以,在多个并发的提交commit的时候,他们会等待正在处理的commit保存到磁盘后在操做,从而下降了效率。而apply只是原子的提交到内存,后面有调用apply的函数的将会直接覆盖前面的内存数据,这样从必定程度上提升了不少效率。 3. apply方法不会提示任何失败的提示。
**注意点: **
0、每次调用commit()、apply()都会将整个settings所有写到文件中,即便你只改动了一个setting。由于它是基于全局的,而不是增量的,因此你的客户端代码中必定不要出现一个putXXX就紧跟着一个commit/apply,而是put完全部你要的改动,最后调用一次commit/apply。 一、因为在一个进程中,SharedPreference是单实例,通常不会出现并发冲突,若是对提交的结果不关心的话,建议使用apply。二、固然须要确保提交成功且有后续操做的话,仍是须要用commit(利用返回值)的。
三、**源码中多线程同步问题:**SharedPreference经过一个标志来控制多线程并发读写的,数据提交的时候,会把标志加一,数据提交完毕的时候会减一,所以若是判断到标志大于0的话就证实还有数据没有提交完成,那么就把数据集(Map)从新拷贝一份再进行后续提交操做。
四、**多进程中:**SharePreferences的可靠性会降低。
SharedPreference的xml文件何时加载到内存中? **
app启动Context初始化的时候,经过SharedPreferencesImpl的startLoadFromDisk中会起一个线程调用loadFromDiskLocked从磁盘上加载数据。
若是一个应用中有好几个sharedPreferences时,每一个sp对应的SharedPreferencesImpl都会各自起一个线程去把xml中的数据加载到map中,后面全部的getXXX方法实际上都是从内存中取数据,不会再有读磁盘的动做了。
**注意:**SharedPreference的序列化和解析的操做都是在内存中完成,因为每个DVM分配的堆内存通常最大只有16M,所以不建议在SharedPreference中保存太大的数据。
30**、Activity与Fragment传值问题 **
一、findFragmentByTag或者getActivity得到对方的引用(强转)以后,再相互调用对方的public方法,耦合度高。
二、经过Bundle的方法进行传值,fragment.setArguments()
三、经过EventBus或者RxBus,耦合度低。
31**、Activity相关 **
Activity生命周期 **
Activity 从建立到销毁有多种状态,从一种状态到另外一种状态时会激发相应的回调方法,这些回调方法包括:
onCreate onStart onResume onPause onStop onDestroy
其实这些方法都是两两对应的,onCreate 建立与onDestroy 销毁;onStart 可见与onStop 不可见;onResume 可编辑(即焦点)与onPause;在Activity 被onStop 后,可是没有被onDestroy,在再次启动此Activity 时就调用onRestart(而再也不调用onCreate)方法;若是被onDestroy 了,则是调用onCreate 方法。
** **
Activity的启动原理(大概把过程说出来) **
1.不管是经过Launcher来启动Activity,仍是经过Activity内部调用startActivity接口来启动新的Activity,都经过Binder进程间通讯进入到ActivityManagerService进程中,而且调用ActivityManagerService.startActivity接口;
2.ActivityManagerService调用ActivityStack.startActivityMayWait来作准备要启动的Activity的相关信息;
3.ActivityStack通知ApplicationThread要进行Activity启动调度了,这里的ApplicationThread表明的是调用ActivityManagerService.startActivity接口的进程,对于经过点击应用程序图标的情景来讲,这个进程就是Launcher了,而对于经过在Activity内部调用startActivity的情景来讲,这个进程就是这个Activity所在的进程了;
4.ApplicationThread不执行真正的启动操做,它经过调用.activityPaused接口进入到ActivityManagerService进程中,看看是否须要建立新的进程来启动Activity;
5.对于经过点击应用程序图标来启动Activity的情景来讲,ActivityManagerService在这一步中,会调用startProcessLocked来建立一个新的进程,而对于经过在Activity内部调用startActivity来启动新的Activity来讲,这一步是不须要执行的,由于新的Activity就在原来的Activity所在的进程中进行启动;
6.ActivityManagerServic调用ApplicationThread.scheduleLaunchActivity接口,通知相应的进程执行启动Activity的操做;
7.ApplicationThread把这个启动Activity的操做转发给ActivityThread,ActivityThread经过ClassLoader导入相应的Activity类,而后把它启动起来。
**两个Activity 之间跳转时必然会执行的是哪几个方法? **
通常状况下好比说有两个activity,分别叫A,B,当在A 里面激活B 组件的时候, A 会调用onPause()方法,而后B 调用onCreate() ,onStart(), onResume()。
这个时候B 覆盖了窗体, A 会调用onStop()方法. 若是B 是个透明的,或者是对话框的样式, 就不会调用A 的onStop()方法。
**异常状态下的Activity生命周期 **
资源相关的系统配置发生改变或者资源不足:例如屏幕旋转,当前Activity会销毁,而且在onStop以前回调onSaveInstanceState保存数据,在从新建立Activity的时候在onStart以后回调onRestoreInstanceState。其中Bundle数据会传到onCreate(不必定有数据)和onRestoreInstanceState(必定有数据)。 防止屏幕旋转的时候重建,在清单文件中添加配置: android:configChanges="orientation"。屏幕旋转的时候会回调onConfigurationChanged方法。
Activity的启动模式** 一、standard:每次激活Activity时(startActivity),都建立Activity实例,并放入任务栈; 二、singleTop:若是某个Activity本身激活本身,即任务栈栈顶就是该Activity,则不须要建立,其他状况都要建立Activity实例; 三、singleTask:若是要激活的那个Activity在任务栈中存在该实例,则不须要建立,只须要把此Activity放入栈顶,即把该Activity以上的Activity实例都pop,并调用其onNewIntent;可是getIntent方法返回的仍是旧的Intent。 四、singleInstance:启用新的任务栈建立Activity实例,若是应用2也要激活Activity,则不须要建立,两应用共享该Activity实例。
32**、Service相关,Service与Activity之间的交互-利用进程间通讯的方式 **
Service运行所在的进程**:不配置的状况下默认在当前app进程中的主线程中运行,所以不能执行耗时操做。
Service的两种启动方式 **
Activity 经过bindService(Intent service, ServiceConnection conn, int flags)跟Service 进行绑定,当绑定成功的时候Service 会将代理对象经过回调的形式传给conn,这样咱们就拿到了Service 提供的服务代理对象。在Activity 中能够经过startService 和bindService 方法启动Service。通常状况下若是想获取Service 的服务对象那么确定须要经过bindService()方法,好比音乐播放器,第三方支付等。若是仅仅只是为了开启一个后台任务那么能够使用startService()方法。
**非绑定模式:**当第一次调用startService 的时候执行的方法依次为onCreate()、onStartCommand(),(onStart())。当Service 关闭的时候调用onDestory 方法。
**绑定模式:**第一次bindService()的时候,执行的方法为onCreate()、onBind()解除绑定的时候会执行onUnbind()、onDestory()。
**注意 **
一、Service 实例只会有一个,也就是说若是当前要启动的Service 已经存在了那么就不会再次建立该Service 固然也不会调用onCreate()方法。
二、一个Service 能够被多个客户进行绑定,只有全部的绑定对象都执行了onBind()方法后该Service 才会销毁,不过若是在混合模式下,有一个客户执行了onStart()方法,那么这个时候若是全部的bind 客户都执行了unBind()该Service 也不会销毁。
**IntentService **
Service 自己存在两个问题:
一、Service 不会专门启动一条单独的进程,Service 与它所在应用位于同一个进程中;
二、Service 也不是专门一条新线程,所以不该该在Service 中直接处理耗时的任务;
IntentService的优势: **
会建立独立的worker 线程来处理全部的Intent 请求;
会建立独立的worker 线程来处理onHandleIntent()方法实现的代码,无需处理多线程问题;
全部请求处理完成后,IntentService 会自动中止,无需调用stopSelf()方法中止Service;
为Service 的onBind()提供默认实现,返回null;
为Service 的onStartCommand 提供默认实现,将请求Intent 添加到队列中;
IntentService的原理: **
IntentService在内部实际上是经过线程以及Handler实现的,当有新的Intent到来的时候,会在onCreate中建立线程,Looper以及Handler。在onStart中经过Handler通知子线程去回调onHandleIntent方法去处理这个Intent,处理完毕之后就经过stopSelf方法销毁自身。所以使用IntentService可以节省系统资源。
**如何让Service成为前置进程? **
在onStartCommand中发一个Notification通知。
**Service **的onStartCommand 方法有几种返回值?各表明什么意思? **
有四种返回值,不一样值表明的意思以下:
一、START_STICKY:若是service进程被kill掉,保留service 的状态为开始状态,但不保留递送的intent对象。随后系统会尝试从新建立service,因为服务状态为开始状态,因此建立服务后必定会调用onStartCommand方法。若是在此期间没有任何启动命令被传递到service,那么参数Intent 将为null。
二、START_NOT_STICKY:“非粘性的”。使用这个返回值时,若是在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
三、START_REDELIVER_INTENT:重传Intent。使用这个返回值时,若是在执行完onStartCommand后,服务被异常kill 掉,系统会自动重启该服务,并将Intent 的值传入。
四、START_STICKY_COMPATIBILITY:START_STICKY 的兼容版本,但不保证服务被kill 后必定能重启。
**Service **的onRebind(Intent)方法在什么状况下会执行? **
若是在onUnbind()方法返回true 的状况下会执行,不然不执行。
33**、广播 **
**内部通讯实现机制:**经过Android 系统的Binder 机制实现通讯。
**广播的两种分类: **
无序广播:彻底异步,逻辑上能够被任何广播接收者接收到。优势是效率较高。缺点是一个接收者不能将处理结
果传递给下一个接收者,并没有法终止广播intent 的传播。(优先级对无序广播也会生效)
有序广播:按照被接收者的优先级顺序,在被接收者中依次传播。每一个接收者有权终止广播,可是若是设置了最终接收者除外。若是传播过程当中没有广播被终止,最终接收者会回调两次onReceive,第一次是按照正常顺序触发的,第二次是最终接受触发。
**判断广播类型:**在onReceive方法中经过isOrderedBroadcast()方法
**注册:**广播接收者能够在清单文件中设置,也能够在代码中设置,可是要注意注销,不然会引起内存泄漏。
**动态注册的优先级是经过注册前后来肯定的,先注册的接收者优先级高。 **
**广播的生命周期 **
BroadCastReceiver 的生命周期
一、广播接收者的生命周期很是短暂的,在接收到广播的时候建立,onReceive()方法结束以后销毁;
二、广播接收者中不要作一些耗时的工做,不然会弹出Application No Response 错误对话框;(不能超过10秒)
三、最好也不要在广播接收者中建立子线程作耗时的工做,由于广播接收者被销毁后进程就成为了空进程,很容易
被系统杀掉;最好新开一个Service**来实现;
**如何让广播在指定app中才能接收?即广播自定义权限 **
一、在清单文件中经过permission标签订义自定义权限,而后uses-permission声明这个权限
二、在指定app中也一样作以上操做,定义广播接收者时候也要添加permission属性。
34**、ContentProvider相关 **
**简要介绍ContentProvider如何实现了应用程序之间的数据共享? **
一、APP若是须要把数据共享出去,先要自定义ContentProvider,实现CURD方法,在清单文件中注册。
二、第三方APP就能够经过ContentResolver进行数据的操做。
三、用户能够经过注册ContentObserver对数据提供者的数据变化进行监听,例如监听短信数据库来实现短信验证码自动填写。
35**、SurfaceView与View的区别 **
区别:surfaceView是在一个新起的单独线程中能够从新绘制画面,而View必须在UI的主线程中更新画面。那么在UI的主线程中更新画面 可能会引起问题,好比你更新画面的时间过长,那么你的主UI线程会被你正在画的函数阻塞。那么将没法响应按键,触屏等消息。当使用surfaceView 因为是在新的线程中更新画面因此不会阻塞你的UI主线程。但这也带来了另一个问题,就是事件同步。好比你触屏了一下,你须要surfaceView中 thread处理,通常就须要有一个event queue的设计来保存touch event,这会稍稍复杂一点,由于涉及到线程同步。
**因此基于以上,根据游戏特色,通常分红两类。 **
1 被动更新画面的。好比棋类,这种用view就行了。由于画面的更新是依赖于onTouch 来更新,能够直接使用 invalidate。 由于这种状况下,这一次Touch和下一次的Touch须要的时间比较长些,不会产生影响。
2 主动更新。好比一我的在一直跑动。这就须要一个单独的thread不停的重绘人的状态,避免阻塞main UI thread。因此显然view不合适,须要surfaceView来控制。
Scroller的原理
public classMyView extendsView {
private Context mContex
Scroller mScroller =****newScroller**(mContext);**
private void smoothScrollTo**(intdestX,intdestY)****{**
int scrollX = getScrollX**();**
//计算滑动距离,startScroll保存参数
int delta = destX - scrollX**;**
mScroller**.startScroll(scrollX,0,destX,0);**
}
@Override
public void computeScroll**()****{**
if **(mScroller.computeScrollOffset())****{// **
//滑动而且刷新
scrollTo**(mScroller.getCurrX(),mScroller.getCurrY());**
postInvalidate**();**
}
}
}** **
** **
**Scroller****执行流程里面的三个核心方法以及滑动的原理: **
mScroller.startScroll()
mScroller.computeScrollOffset()
view.computeScroll()
一、在mScroller.startScroll()中为滑动作了一些初始化准备。
好比:起始坐标,滑动的距离和方向以及持续时间(有默认值),动画开始时间等
二、mScroller.computeScrollOffset()方法主要是根据当前已经消逝的时间来计算当前的坐标点。
由于在mScroller.startScroll()中设置了动画时间,那么在computeScrollOffset()方法中依据已经消逝的时间就很容易获得当前时刻应该所处的位置并将其保存在变量mCurrX和mCurrY中。除此以外该方法还可判断动画是否已经结束。
三、postInvalidate方法会致使View的重绘,重绘的时候又会回调computeScroll方法去进行View的滑动,如此往复。
36**、工具相关 **
**请介绍下adb、ddms、aapt 的做用 **
**adb **Android Debug Bridge ,Android调试桥的意思。一个命令行工具,Android的主要调试工具。
ddms Dalvik Debug Monitor Service,dalvik 调试监视服务。ddms 是一个在adb 基础上的一个图形化工具。ddms是程序执行的查看器,能够查线程和堆栈信息。而traceView是ddms中的一部分,用于程序性能分析。
aapt 即Android Asset Packaging Tool,在SDK 的build-tools 目录下。该工具能够查看,建立,更新ZIP格式的文档附件(zip, jar, apk)。也可将资源文件编译成二进制文件,尽管咱们没有直接使用过该工具,可是开发工具会使用这个工具打包apk 文件构成一个Android 应用程序。
37**、ListView等列表控件 **
**优化问题: **
一、使用ViewHolder模式,建立静态ViewHolder类,复用ConverView 二、使用分页加载 三、使用弱引用去引用一些控件。由于控件上有Context对象,这样作防止了内存泄漏。
**ViewHolder ****为何要声明为静态类? **
非静态内部类拥有外部类对象的强引用,所以为了不对外部类(外部类极可能是Activity)对象的引用,那么最
好将内部类声明为static 的。
使用Handler的时候:自定义的Handler内部类应该声明为static,而且使用弱引用去引用Context等,防止Context不能正常销毁而致使内存泄漏。
ListView****中的设计模式**:adapter模式、观察者模式、享元模式(ItemView的复用)
ScrollView****中嵌套ListView问题: **
问题:**例如在滑动页面中嵌套一个显示物流信息的ListView,这样会致使ListView显示不全,只显示一个条目。
解决办法:在ScrollView里面加一层LinearLayout,经过代码动态设置ListView的高度。
38****、视屏播放 **
一、MediaPlayer 二、VideoView(内部仍是使用了MediaPlayer) 三、第三方开源万能播放器VitamioPlayer
39****、Intent **
Intent ****传递数据时,能够传递哪些类型数据? **
Intent 能够传递的数据类型很是的丰富,java 的基本数据类型和String 以及他们的数组形式均可以,除此之
外还能够传递实现了Serializable 和Parcelable 接口的对象。
Serializable ****(Java)和Parcelable (Android)的区别 **
1.在使用内存的时候,Parcelable 类比Serializable 性能高,因此推荐使用Parcelable 类。
2.Serializable 在序列化的时候会产生大量的临时变量,从而引发频繁的GC。
3.Parcelable 不能使用在要将数据存储在磁盘上的状况。尽管Serializable 效率低点,但在这种状况下,仍是建议用Serializable 。
实现:
1 Serializable 的实现,只须要继承Serializable ,指定序列化ID便可。这只是给对象打了一个标记,系统会自动将其序列化。
2 Parcelabel 的实现,须要在类中添加一个静态成员变量CREATOR,这个变量须要继承Parcelable.Creator 接口。
40****、Fragment相关**
FragmentManager****的add方法与replace方法的异同: **
一、add 的时候是把全部的Fragment 一层一层的叠加到了FrameLayout 上
二、replace 的话首先将该容器中的其余Fragment 去除掉而后将当前Fragment 添加到容器中,所以使用replace方法的时候要注意会触发onDestroyView。**
三、通常思路是先add进来,而后经过hide以及show来进行Fragment的切换,此时Fragment的生命周期没有变化**。
Fragment****实现Activity压栈和出栈的效果**:经过addToBackStack方法实现,内部维护了一个双向链表。
Activity和Fragment之间你是怎么传值的? **
41****、Android中的动画 **
动画分类:帧动画,补间动画,属性动画(实际View的移动,点击事件会跟随)
如何为Activity或者Fragment添加动画? **
一、自定义主题,复写相应的属性,以下图所示 二、在finish或者startActivity以后调用overridePendingTransition
42****、签名、多渠道打包,上线流程 **
签名简介:**在Android 系统中,全部安装到系统的应用程序都必有一个数字证书,此数字证书用于标识应用程序的做者和在 **
应用程序之间创建信任关系。Android 系统要求每个安装进系统的应用程序都是通过数字证书签名的。
签名好处:**(1)有利于程序升级,当新版程序和旧版程序的数字证书相同时,Android 系统才会认为这两个程序是同一个程序
的不一样版本。若是新版程序和旧版程序的数字证书不相同,则Android 系统认为他们是不一样的程序,并产生冲突,会
要求新程序更改包名。
(2)有利于程序的模块化设计和开发。Android 系统容许拥有同一个数字签名的程序运行在一个进程中,Android程序会将他们视为同一个程序。因此开发者能够将本身的程序分模块开发,而用户只须要在须要的时候下载适当的模块。
在签名时,须要考虑数字证书的有效期: **
(1)数字证书的有效期要包含程序的预计生命周期,一旦数字证书失效,持有改数字证书的程序将不能正常升级。
(2)若是多个程序使用同一个数字证书,则该数字证书的有效期要包含全部程序的预计生命周期。
(3)Android Market 强制要求全部应用程序数字证书的有效期要持续到2033 年10 月22 日之后。