




已阅读5页,还剩24页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、 Android ANRANR:Application Not Responding,即应用无响应。ANR一般有三种类型:1. KeyDispatchTimeout(5 seconds) -主要类型按键或触摸事件在特定时间内无响应2. BroadcastTimeout(10 seconds) -BroadcastReceiver在特定时间内无法处理完成3. ServiceTimeout(20 seconds) -小概率类型 Service在特定的时间内无法处理完成超时时间的计数一般是从按键分发给app开始。超时的原因一般有两种:(1)当前的事件没有机会得到处理(即UI线程正在处理前一个事件,没有及时的完成或者looper被某种原因阻塞住了)(2)当前的事件正在处理,但没有及时完成如何避免KeyDispatchTimeout1. UI线程尽量只做跟UI相关的工作2. 耗时的工作(比如数据库操作,I/O,连接网络或者别的有可能阻碍UI线程的操作)把它放入单独的线程处理3. 尽量用Handler来处理UIthread和别的thread之间的交互说了那么多的UI线程,那么哪些属于UI线程呢?UI线程主要包括如下:1. Activity:onCreate(), onResume(), onDestroy(), onKeyDown(), onClick(),etc2. AsyncTask: onPreExecute(), onProgressUpdate(), onPostExecute(), onCancel,etc3. Mainthread handler: handleMessage(), post*(runnable r), etc4. other从LOG可以看出ANR的类型,CPU的使用情况,如果CPU使用量接近100%,说明当前设备很忙,有可能是CPU饥饿导致了ANR如果CPU使用量很少,说明主线程被BLOCK了如果IOwait很高,说明ANR有可能是主线程在进行I/O操作造成的除了看LOG,解决ANR还得需要trace.txt文件,如何获取呢?可以用如下命令获取$chmod 777 /data/anr$rm /data/anr/traces.txt$ps$kill -3 PIDadbpull data/anr/traces.txt ./mytraces.txt 从trace.txt文件,看到最多的是如下的信息:说明主线程在等待下条消息进入消息队列如何调查并解决ANR1. 首先分析log2. 从trace.txt文件查看调用stack.3. 看代码4. 仔细查看ANR的成因(iowait?block?memoryleak?)2、 android 事件分发1、基础知识(1) 所有Touch事件都被封装成了MotionEvent对象,包括Touch的位置、时间、历史记录以及第几个手指(多指触摸)等。 (2) 事件类型分为ACTION_DOWN, ACTION_UP, ACTION_MOVE, ACTION_POINTER_DOWN, ACTION_POINTER_UP, ACTION_CANCEL,每个事件都是以ACTION_DOWN开始ACTION_UP结束。 (3) 对事件的处理包括三类,分别为传递dispatchTouchEvent()函数、拦截onInterceptTouchEvent()函数、消费onTouchEvent()函数和OnTouchListener 2、传递流程(1) 事件从Activity.dispatchTouchEvent()开始传递,只要没有被停止或拦截,从最上层的View(ViewGroup)开始一直往下(子View)传递。子View可以通过onTouchEvent()对事件进行处理。 (2) 事件由父View(ViewGroup)传递给子View,ViewGroup可以通过onInterceptTouchEvent()对事件做拦截,停止其往下传递。 (3) 如果事件从上往下传递过程中一直没有被停止,且最底层子View没有消费事件,事件会反向往上传递,这时父View(ViewGroup)可以进行消费,如果还是没有被消费的话,最后会到Activity的onTouchEvent()函数。 (4) 如果View没有对ACTION_DOWN进行消费,之后的其他事件不会传递过来。 (5) OnTouchListener优先于onTouchEvent()对事件进行消费。 上面的消费即表示相应函数返回值为true。Android中事件传递按照从上到下进行层级传递,事件处理从Activity开始到ViewGroup再到View。 事件传递方法包括dispatchTouchEvent、onTouchEvent、onInterceptTouchEvent,其中前两个是View和ViewGroup都有的,最后一个是只有ViewGroup才有的方法。这三个方法的作用分别是负责事件分发、事件处理、事件拦截。 onTouch事件要先于onClick事件执行,onTouch在事件分发方法dispatchTouchEvent中调用,而onClick在事件处理方法onTouchEvent中被调用,onTouchEvent要后于dispatchTouchEvent方法的调用。用户点击屏幕产生Touch(包括DOWN、UP、MOVE,本文分析的是DOWN)事件 - InputManager - WindowManagerService.dispatchPointer() - IWindow.Stub - ViewRoot.dispatchPointer() - PhoneWindow.DecorView.dispatchTouchEvent() - Activity.dispatchTouchEvent() - PhoneWindow.superDispatchTouchEvent - PhoneWindow.DecorView.superDispatchTouchEvent - ViewGroup.dispatchTouchEvent() - ViewGroup.dispatchTransformedTouchEvent() - 子View.dispatchTouchEvent() - 子View.onTouch() - 子View.onTouchEvent() - 事件被消费结束。(这个过程是由上往下传导)3、 view的绘制流程一共三步:Measure(测量及定位)、layout(排版及布局)、draw(绘制)。绘制background,如果需要,保存canvas状态,绘制view的上下文,绘制子view,如果需要,绘制边缘,恢复canvas状态,绘制滚动条。4、 进程通信机制4种跨进程通讯的方式:Activity、ContentProvider、Broadcast和AIDL Service。其中Activity可以跨进程调用其他应用程序的Activity;ContentProvider可以访问其他应用程序返回的 Cursor对象;Broadcast采用的是被动接收的方法,也就是说,客户端只能接收广播数据,而不能向发送广播的程序发送信息。AIDL Service可以将程序中的某个接口公开,这样在其他的应用程序中就可以象访问本地对象一样访问AIDL服务对象了。这4种跨进程通讯的方式可以应用在 不同的场合,例如,在需要显示可视化的界面时可以用Activity,需要返回记录集时可以用ContentProvider。看一下如何将应用程序的Activity共享出来,读者可按如下几步来共享Activity:1. 在AndroidManifest.xml文件中指定Action。指定Action要使用标签,并在该标签的android:name属性中指定Action2. 在AndroidManifest.xml文件中指定访问协议。在指定Uri(Intent类的第2个参数)时需要访问协议。访问协议需要使 用标签的android:scheme属性来指定。如果该属性的值是“abc”,那么Uri就应该是“abc:/Uri的主体 部分”,也就是说,访问协议是Uri的开头部分。3. 通过getIntent().getData().getHost()方法获得协议后的Uri的主体部分。这个Host只是个称谓,并不一定是主机名。读者可以将其看成是任意的字符串。4. 从Bundle对象中获得其他应用程序传递过来的数据。5. 这一步当然是获得数据后做进一步的处理了。至于如何处理这些数据,就得根据具体的需求决定了。5、 View的绘制优化,不阻塞ui线程数据和实现尽量分离、一切有可能引起阻塞的方法等,如非必要,尽量都用在非UI线程中,用handler做为通信工具、耗时的操作不要放在UI线程中,尝试异步加载控件。onDraw方法内尽量不要创建对象,否则容易出现内存抖动。内存抖动是因为大量的对象被创建又在短时间内马上被释放。a 布局优化。优化layout的层级:避免嵌套。使用merge标签优化层级使用include标签重用Layout按需载入视图:不需要立即加载的布局,设置为GONE,系统会跳过,不加载。使用ViewStub 实现按需加载ListView的优化:使用后台线程,在 View Holder 中填入视图对象,getView不要做复杂的操作。尽量使用RelativeLayout,可以减少层级的嵌套。慎用LinearLayout的layout_weight属性,可以使用RelativeLayout的centerHorizontal=”true”、toLeft、toRight代替b 绘制优化。避免Overdraw就是过度绘制合理选择控件容器、去掉window的默认背景、去掉其他不必要的背景、ClipRect & QuickReject(不可见的裁剪掉)、善用draw9patch、慎用Alpha、避免“OverDesign(过度设计)”6、 职业规划回答提示:这是每一个应聘者都不希望被问到的问题,但是几乎每个人都会被问到,比较多的答案是“管理者”。但是近几年来,许多公司都已经建立了专门的技术途径。这些工作地位往往被称作“顾问”、“参议技师”或“高级软件工程师”等等。当然,说出其他一些你感兴趣的职位也是可以的,比如产品销售部经理,生产部经理等一些与你的专业有相关背景的工作。要知道,考官总是喜欢有进取心的应聘者,此时如果说“不知道”,或许就会使你丧失一个好机会。最普通的回答应该是“我准备在技术领域有所作为”或“我希望能按照公司的管理思路发展”。7、 你还有什么问题要问吗?回答提示:企业的这个问题看上去可有可无,其实很关键,企业不喜欢说“没问题”的人,因为其很注重员工的个性和创新能力。企业不喜欢求职者问个人福利之类的问题,如果有人这样问:贵公司对新入公司的员工有没有什么培训项目,我可以参加吗?或者说贵公司的晋升机制是什么样的?企业将很欢迎,因为体现出你对学习的热情和对公司的忠诚度以及你的上进。8、 Android内存优化1.Reckon(计算)首先需要知道你的app所消耗内存的情况,知己知彼才能百战不殆2.Reduce(减少)消耗更少的资源3.Reuse(重用)当第一次使用完以后,尽量给其他的使用5.Recycle(回收)回收资源4.Review(检查)回顾检查你的程序,看看设计或代码有什么不合理的地方。1) 珍惜Services资源如果你的应用需要在后台使用service,除非它被触发并执行一个任务,否则其他时候service都应该是停止状态。另外需要注意当这个service完成任务之后因为停止service失败而引起的内存泄漏。限制你的service的最好办法是使用IntentService, 它会在处理完交代给它的intent任务之后尽快结束自己。2) 当UI隐藏时释放内存当用户切换到其它应用并且你的应用 UI不再可见时,你应该释放你的应用UI上所占用的所有内存资源。在这个时候释放UI资源可以显著的增加系统缓存进程的能力,它会对用户体验有着很直接的影响。为了能够接收到用户离开你的UI时的通知,你需要实现Activtiy类里面的onTrimMemory()回调方法。你应该使用这个方法来监听到TRIM_MEMORY_UI_HIDDEN级别的回调,此时意味着你的UI已经隐藏,你应该释放那些仅仅被你的UI使用的资源。请注意:你的应用仅仅会在所有UI组件的被隐藏的时候接收到onTrimMemory()的回调并带有参数TRIM_MEMORY_UI_HIDDEN。这与onStop()的回调是不同的,onStop会在activity的实例隐藏时会执行,例如当用户从你的app的某个activity跳转到另外一个activity时前面activity的onStop()会被执行。因此你应该实现onStop回调,并且在此回调里面释放activity的资源,例如释放网络连接,注销监听广播接收者。除非接收到onTrimMemory(TRIM_MEMORY_UI_HIDDEN)的回调,否者你不应该释放你的UI资源。这确保了用户从其他activity切回来时,你的UI资源仍然可用,并且可以迅速恢复activity。3) 当内存紧张时释放部分内存在你的app生命周期的任何阶段,onTrimMemory的回调方法同样可以告诉你整个设备的内存资源已经开始紧张。你应该根据onTrimMemory回调中的内存级别来进一步决定释放哪些资源。因为onTrimMemory()的回调是在API 14才被加进来的,对于老的版本,你可以使用onLowMemory)回调来进行兼容。onLowMemory相当与TRIM_MEMORY_COMPLETE。4) 检查你应该使用多少的内存正如前面提到的,每一个Android设备都会有不同的RAM总大小与可用空间,因此不同设备为app提供了不同大小的heap限制。你可以通过调用getMemoryClass()来获取你的app的可用heap大小。如果你的app尝试申请更多的内存,会出现OutOfMemory的错误。在一些特殊的情景下,你可以通过在manifest的application标签下添加largeHeap=true的属性来声明一个更大的heap空间。如果你这样做,你可以通过getLargeMemoryClass()来获取到一个更大的heap size。然而,能够获取更大heap的设计本意是为了一小部分会消耗大量RAM的应用(例如一个大图片的编辑应用)。不要轻易的因为你需要使用大量的内存而去请求一个大的heap size。只有当你清楚的知道哪里会使用大量的内存并且为什么这些内存必须被保留时才去使用large heap. 因此请尽量少使用large heap。使用额外的内存会影响系统整体的用户体验,并且会使得GC的每次运行时间更长。在任务切换时,系统的性能会变得大打折扣。另外, large heap并不一定能够获取到更大的heap。在某些有严格限制的机器上,large heap的大小和通常的heap size是一样的。因此即使你申请了large heap,你还是应该通过执行getMemoryClass()来检查实际获取到的heap大小。5) 避免bitmaps的浪费当你加载一个bitmap时,仅仅需要保留适配当前屏幕设备分辨率的数据即可,如果原图高于你的设备分辨率,需要做缩小的动作。请记住,增加bitmap的尺寸会对内存呈现出2次方的增加,因为X与Y都在增加。6) 使用优化的数据容器利用Android Framework里面优化过的容器类,例如SparseArray, SparseBooleanArray, 与 LongSparseArray。 通常的HashMap的实现方式更加消耗内存,因为它需要一个额外的实例对象来记录Mapping操作。另外,SparseArray更加高效在于他们避免了对key与value的autobox自动装箱,并且避免了装箱后的解箱。7) 请注意内存开销对你所使用的语言与库的成本与开销有所了解,从开始到结束,在设计你的app时谨记这些信息。通常,表面上看起来无关痛痒(innocuous)的事情也许实际上会导致大量的开销。例如:Enums的内存消耗通常是static constants的2倍。你应该尽量避免在Android上使用enums。在Java中的每一个类(包括匿名内部类)都会使用大概500 bytes。每一个类的实例花销是12-16 bytes。往HashMap添加一个entry需要额一个额外占用的32 bytes的entry对象。8) 请注意代码“抽象”通常,开发者使用抽象作为”好的编程实践”,因为抽象能够提升代码的灵活性与可维护性。然而,抽象会导致一个显著的开销:通常他们需要同等量的代码用于可执行。那些代码会被map到内存中。因此如果你的抽象没有显著的提升效率,应该尽量避免他们。9) 为序列化的数据使用nano protobufsProtocol buffers是由Google为序列化结构数据而设计的,一种语言无关,平台无关,具有良好扩展性的协议。类似XML,却比XML更加轻量,快速,简单。如果你需要为你的数据实现协议化,你应该在客户端的代码中总是使用nano protobufs。通常的协议化操作会生成大量繁琐的代码,这容易给你的app带来许多问题:增加RAM的使用量,显著增加APK的大小,更慢的执行速度,更容易达到DEX的字符限制。10) 避免使用依赖注入框架使用类似Guice或者RoboGuice等framework injection包是很有效的,因为他们能够简化你的代码。然而,那些框架会通过扫描你的代码执行许多初始化的操作,这会导致你的代码需要大量的RAM来mapping代码,而且mapped pages会长时间的被保留在RAM中。11) 谨慎使用第三方libraries,如果可以,尽量裁剪无关的class很多开源的library代码都不是为移动网络环境而编写的,如果运用在移动设备上,这样的效率并不高。当你决定使用一个第三方library的时候,你应该针对移动网络做繁琐的迁移与维护的工作。即使是针对Android而设计的library,也可能是很危险的,因为每一个library所做的事情都是不一样的。例如,其中一个lib使用的是nano protobufs, 而另外一个使用的是micro protobufs。那么这样,在你的app里面就有2种protobuf的实现方式。这样的冲突同样可能发生在输出日志,加载图片,缓存等等模块里面。同样不要陷入为了1个或者2个功能而导入整个library的陷阱。如果没有一个合适的库与你的需求相吻合,你应该考虑自己去实现,而不是导入一个大而全的解决方案。12) 优化整体性能官方有列出许多优化整个app性能的文章:Best Practices for Performance。这篇文章就是其中之一。有些文章是讲解如何优化app的CPU使用效率,有些是如何优化app的内存使用效率。你还应该阅读optimizing your UI来为layout进行优化。同样还应该关注lint工具所提出的建议,进行优化。13) 使用ProGuard来剔除不需要的代码ProGuard能够通过移除不需要的代码,重命名类,域与方法等方对代码进行压缩,优化与混淆。使用ProGuard可以使得你的代码更加紧凑,这样能够使用更少mapped代码所需要的RAM。14) 对最终的APK使用zipalign进行校准在编写完所有代码,并通过编译系统生成APK之后,你需要使用zipalign对APK进行重新校准。如果你不做这个步骤,会导致你的APK需要更多的RAM,因为一些类似图片资源的东西不能被mapped。Notes: Google Play不接受没有经过zipalign的APK。15) 分析你的RAM使用情况一旦你获取到一个相对稳定的版本后,需要分析你的app整个生命周期内使用的内存情况,并进行优化。可以使用MAT等工具。16) 使用多进程如果合适的话,有一个更高级的技术可以帮助你的app管理内存使用:通过把你的app组件切分成多个组件,运行在不同的进程中。这个技术必须谨慎使用,大多数app都不应该运行在多个进程中。因为如果使用不当,它会显著增加内存的使用,而不是减少。当你的app需要在后台运行与前台一样的大量的任务的时候,可以考虑使用这个技术。例如音乐播放器,可以切分成2个进程:一个用来操作UI,另外一个用来后台的Service.9、 Android包体压缩优化1)用 Lint 工具(当然 Lint 工具还有别的强大功能,我只是用了两个):1.查找没有引用的资源文件,清除然后给 apk 瘦身。2.布局优化建议(这个可以直接用 Hierarchy Viewer)。2)使用图片压缩工具对你apk中的资源文件中的图片进行压缩。一些纯色的图片用颜色值代替。3)proguard代码混淆,剔除不需要的代码,可以大大减小apk的大小4)去除不再使用的资源5)对最终的APK使用zipalign6)选择合适的library,甚至可以进行jar裁剪7)对不同平台进行分别打包,只引入本平台的.so文件,缺点是这个apk只能在一个平台上跑8)有选择性的提供hdpi,xhdpi,xxhdpi的图片资源。建议优先提供xhdpi的图片,对于mdpi,ldpi与xxxhdpi根据需要提供有差异的部分即可。9)资源尽量使用体积小的格式。例如图片资源转为webp,也能有效压缩体积10)部分资源可以考虑用网络资源代替,保存到本地,代码复杂度增加。10、 Android电量优化尽量减少唤醒屏幕的次数与持续的时间(屏幕是用电大户),用WakeLock来处理唤醒的问题,能够正确执行唤醒操作并根据设定及时关闭操作进入睡眠状态,使用 wakelock.acquice() 方法,一定要加上超时处理(例如释放锁)。等到设备处于充电状态或者电量充足的时候才进行耗时耗电操作(如分享传送数据、图片处理等)触发网络请求的操作,每次都会保持无线信号持续一段时间,我们可以把零散的网络请求打包进行一次操作,避免过多的无线信号引起的电量消耗(例如APP的数据采集)。Battery Historian Tool(Android 5.0)这个工具可以详细查看各类应用的用电情况。android应用的耗电主要在以下三个方面:大数据量的传输。不停的在网络间切换。解析大量的文本数据。 并提出了相关的优化建议: 在需要网络连接的程序中,首先检查网络连接是否正常,如果没有网络连接,那么就不需要执行相应的程序。 使用效率高的数据格式和解析方法,推荐使用JSON和Protobuf。 目在进行大数据量下载时,尽量使用GZIP方式下载。 其它:回收java对象,特别是较大的java对像,使用reset方法;对定位要求不是太高的话尽量不要使用GPS定位,可能使用wifi和移动网络cell定位即可;尽量不要使用浮点运算;获取屏幕尺寸等信息可以使用缓存技术,不需要进行多次请求;使用AlarmManager来定时启动服务替代使用sleep方式的定时任务。11、 Android渲染优化Android系统每隔16ms发出VSYNC信号,触发对UI进行渲染,那么整个过程如果保证在16ms以内就能达到一个流畅的画面。那么如果操作超过了16ms还无法进行渲染,还在做别的操作,那么就会导致丢帧的现象,(大家在察觉到APP卡顿的时候,可以看看logcat控制太,会有drop frames类似的警告)。这样的话,绘制就会在下一个16ms的时候才进行绘制,即使只丢一帧,用户也会发现卡顿的(为什么是16ms,16ms意味着着1000/60hz,相当于60fps)解决方法:通过Hierarchy Viewer去检测渲染效率,去除不必要的嵌套及背景通过Show GPU Overdraw去检测Overdraw,最终可以通过移除不必要的背景以及使用canvas.clipRect解决大多数问题。12、 Android属性动画13、 IntentService普通的service ,默认运行在ui main 主线程;这是带有异步处理的service类;异步处理的方法 OnHandleIntent();OnHandleIntent() 处理耗时的操作;Android的进程处理器现在会尽可能的不kill掉你。IntentService是Service的子类,比普通的Service增加了额外的功能。会创建独立的worker线程来处理所有的Intent请求; 会创建独立的worker线程来处理onHandleIntent()方法实现的代码,无需处理多线程问题; 所有请求处理完成后,IntentService会自动停止,无需调用stopSelf()方法停止Service; 为Service的onBind()提供默认实现,返回null; 为Service的onStartCommand提供默认实现,将请求Intent添加到队列中;14、 Android插件化、动态加载随着应用的不断迭代,应用的体积不断增大,项目越来越臃肿,冗余增加.项目新功能的添加,无法确定与用户匹配性,发生严重异常往往牵一发而动全身,只能紧急发布补丁版本,强制用户进行更新.结果频繁的更新,反而容易降低用户使用黏性.或者是公司业务的不断发展,同系的应用越来越多,传统方式需要通过用户量最大的主项目进行引导下载并安装.关键词:pathclassloader、dexclassloader。如下图所示,首先宿主程序会到文件系统比如sd卡去加载apk,然后通过一个叫做proxy的activity去执行apk中的activity。关于动态加载apk,理论上可以用到的有DexClassLoader、PathClassLoader和URLClassLoader。DexClassLoader :可以加载文件系统上的jar、dex、apkPathClassLoader :可以加载/data/app目录下的apk,这也意味着,它只能加载已经安装的apkURLClassLoader :可以加载java中的jar,但是由于dalvik不能直接识别jar,所以此方法在android中无法使用,尽管还有这个类关于jar、dex和apk,dex和apk是可以直接加载的,因为它们都是或者内部有dex文件,而原始的jar是不行的,必须转换成dalvik所能识别的字节码文件,转换工具可以使用android sdk中platform-tools目录下的dx转换命令 :dx -dex -output=dest.jar src.jar每个插件以单独的apk发布,例子有手机qq、淘宝软件15、 Android View中的draw和onDraw有什么区别我们在自定义view的时候只需要重写onDraw(),而没必要去重写draw(),因为onDraw()是draw()方法的一部分。大概扫一下源码就可以明白,draw()这个函数本身会做很多事情,* 1. Draw the background* 2. If necessary, save the canvas layers to prepare for fading* 3. Draw views content* 4. Draw children* 5. If necessary, draw the fading edges and restore layers* 6. Draw decorations (scrollbars for instance)在第三步的时候,它就会调用onDraw()方法,来绘制view的内容。也就是draw会调用onDraw。所以看需要,一般情况下,直接用onDraw绘制view的content就可以了,如果绘制多一点的内容,可以调用draw(),不过Android官方推荐用只用onDraw就可以了。“When implementing a view, do not override this method; instead, you should implement onDraw”16、 Android应用框架应用程序框架呢可以说是一个应用程序的核心,是所有参与开发的程序员共同使用和遵守的约定,大家在其约定上进行必要的扩展,但程序始终保持主体结构的一致性。其作用是让程序保持清晰和一目了然,在满足不同需求的同时又不互相影响。框架主要是指模块(目录)结构清晰容易扩展,不一定需要引入第三方应用框架(有过度设计嫌疑),可以参考MVC、MVP模式的设计思想,构建自己的android项目。17、 Android MVC、MVP、MVVM18、 Dalvik和ART的区别什么是Dalvik: Dalvik是Google公司自己设计用于Android平台的Java虚拟机。Dalvik虚拟机是Google等厂商合作开发的Android移动设备平台的核心组成部分之一。它可以支持已转换为 .dex(即Dalvik Executable)格式的Java应用程序的运行,.dex格式是专为Dalvik设计的一种压缩格式,适合内存和处理器速度有限的系统。Dalvik 经过优化,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个Dalvik 应用作为一个独立的Linux 进程执行。独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭。什么是ART: Android操作系统已经成熟,Google的Android团队开始将注意力转向一些底层组件,其中之一是负责应用程序运行的Dalvik运行时。Google开发者已经花了两年时间开发更快执行效率更高更省电的替代ART运行时。 ART代表Android Runtime,其处理应用程序执行的方式完全不同于Dalvik,Dalvik是依靠一个Just-In-Time (JIT)编译器去解释字节码。开发者编译后的应用代码需要通过一个解释器在用户的设备上运行,这一机制并不高效,但让应用能更容易在不同硬件和架构上运 行。ART则完全改变了这套做法,在应用安装时就预编译字节码到机器语言,这一机制叫Ahead-Of-Time (AOT)编译。在移除解释代码这一过程后,应用程序执行将更有效率,启动更快。ART优点:1、系统性能的显著提升。2、应用启动更快、运行更快、体验更流畅、触感反馈更及时。3、更长的电池续航能力。4、支持更低的硬件。ART缺点:1、更大的存储空间占用,可能会增加10%-20%。2、更长的应用安装时间。总的来说ART的功效就是“空间换时间”。19、 Android热修复/增量更新增量更新的原理,就是将手机上已安装apk与服务器端最新apk进行二进制对比,得到差分包,用户更新程序时,只需要下载差分包,并在本地使用差分包与已安装apk,合成新版apk。apk文件的差分、合成,可以通过开源的二进制比较工具bsdiff来实现,又因为bsdiff依赖bzip2,所以我们还需要用到 bzip2。bsdiff中,bsdiff.c 用于生成差分包,bspatch.c 用于合成文件。弄清楚原理之后,我们想实现增量更新,共需要做3件事:1、在服务器端,用开源的二进制比较工具生成两个版本apk的差分包;2、在手机客户端,使用已安装的apk与这个差分包进行合成,得到新版的微博apk;3、校验新合成的apk文件是否完整,MD5或SHA1是否正确,如正确,则引导用户安装;public static void installApk(Context context, String apkPath) Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.parse(file:/ + apkPath), application/vnd.android.package-archive); context.startActivity(intent); 注意事项:增量更新的前提条件,是在手机客户端能让我们读取到当前应用程序安装后的源apk,如果获取不到源apk,那么就无法进行增量更新了,另外,如果你的应用程序不是很大,比如只有2、3M,那么完全没有必要使用增量更新,增量更新只适用于apk包比较大的情况,比如手机游戏客户端。20、 Android安全问题关键词:android权限(自定义权限)、反汇编(混淆)、apk签名(私有keystore)、系统漏洞(热修复)、PackageManagerService动态permission。可以从以下几个方面来应对Android开发的常见安全问题:应用权限控制。通过控制应用程序的权限防止恶意应用对系统造成破坏,采取的措施包括合理使用系统内置权限和应用程序自定义权限。应用程序签名。采用数字签名为应用程序签名。应用加固。应用加固包括病毒扫描、防注入、防调试、防篡改四个模块,目前行业内已经出现了很多的应用加固解决方案,如360应用加固、腾讯云应用加固、百度应用加固等等。 静态代码分析。通过静态代码分析工具lint监测安全隐患,对代码进行优化。防火墙。必要时为Android设备安装防火墙,以防止远程网络攻击。数据存储加密。采用加密的方式保护应用程序敏感数据,如利用SQLCipher加密SQLite数据库。应用程序组件开发的安全要点。Activity, Service, Content Provider, Broadcast Receiver等组件在代码层面应采取的安全措施。它们每一个都可以通过隐式的Intent方式打开,所以这些组件只要不是对外公开的必须在AndroidManifest里面注明exported为false,禁止其它程序访问我们的组件。对于要和外部交互的组件,应当添加访问权限的控制,还需要要对传递的数据进行安全的校验。21、 Android Hybrid关键点:java和JS的交互(WebView.addJavascriptInterface)、WebView开启JavaScript脚本执行(WebView.loadUrl(javascript:wave();)、WebView设置供JavaScript调用的交互接口开源的框架:PhoneGap、AppCan22、 Android Store上架流程及规则23、 请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系。简单的说,Handler获取当前线程中的 looper对象,looper 用来从存放 Message 的 MessageQueue中取出 Message,再由Handler 进行 Message 的分发和处理.Message Queue(消息队列): 用来存放通过 Handler 发布的消息, 通常附属于某一个创建它的线程,可以通过 Looper.myQueue()得到当前线程的消息队列Handler:可以发布或者处理一个消息或者操作一个 Runnable,通过 Handler发布消息, 消息将只会发送到与它关联的消息队列,然也只能处理该消息队列中的消息Looper:是 Handler 和消息队列之间通讯桥梁,程序组件首先通过 Handler 把消息传递给 Looper,Looper 把消息放入队列。Looper 也把消息队列里的消息广播给所有的HandlerHandler:Handler 接受到消息后调用 handleMessage进行处理Message:消息的类型,在 Handler 类中的 handleMessage 方法中得到单个的消息进行处理在单线程模型下, 为了线程通信问题, Android 设计了一个 Message Queue(消息队列), 线程间可以通过该 Message Queue 并结合 Handler 和 Looper 组件进行信息交换。24、 View, surfaceView, GLSurfaceView的区别View 是最基础的,必须在 UI 主线程内更新画面,速度较慢。SurfaceView 是 view 的子类,类似使用双缓机制,在新的线程中更新画面所以刷新界面速度比 view 快 GLSurfaceView 是 SurfaceView 的子类,opengl 专用的。区别:SurfaceView是从View基类中派生出来的显示类,直接子类有GLSurfaceView和VideoView,可以看出GL和视频播放以及Camera摄像头一般均使用SurfaceViewSurfaceView和View最本质的区别在于,surfaceView是在一个新起的单独线程中可以重新绘制画面而View必须在UI的主线程中更新画面。那么在UI的主线程中更新画面 可能会引发问题,比如你更新画面的时间过长,那么你的主UI线程会被你正在画的函数阻塞。那么将无法响应按键,触屏等消息。当使用surfaceView 由于是在新的线程中更新画面所以不会阻塞你的UI主线程。但这也带来了另外一个问题,就是事件同步。比如你触屏了一下,你需要surfaceView中thread处理,一般就需要有一个event queue的设计来保存touch event,这会稍稍复杂一点,因为涉及到线程同步。25、 根据自己的理解描述下Android数字签名(1)所有的应用程序都必须有数字证书,Android系统不会安装一个没有数字证书的应用程序(2)Android程序包使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签名认证(3)如果要正式发布一个Android ,必须使用一个合适的私钥生成的数字证书来给程序签名,而不能使用adt插件或者ant工具生成的调试证书来发布。(4)数字证书都是有有效期的,Android只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能26、 谈谈对 Android NDK 的理解NDK 全称:Native Development Kit。1、NDK 是一系列工具的集合。 * NDK 提供了一系列的工具,帮助开发者快速开发 C(或 C+)的动态库,并能自动将 so 和 java 应用一起打包成 apk。这些工具对开发者的帮助是巨大的。 * NDK 集成了交叉编译器,并提供了相应的 mk 文件隔离 CPU、平台、ABI 等差异,开发人员只需要简单修改 mk 文件(指出“哪些文件需要编译”、“编译特性要求”等) ,就可以创建出 so。NDK 可以自动地将so 和 Java 应用一起打包,极大地减轻了开发人员的打包工作。2、NDK 提供了一份稳定、功能有限的 API 头文件声明。 Google 明确声明该 API 是稳定的,在后续所有版本中都稳定支持当前发布的 API。从该版本的 NDK 中看出,这些 API 支持的功能非常有限,包含有:C 标准库(libc) 、标准数学库(libm) 、压缩库(libz) 、Log 库(liblog) 。27、 ViewStub的应用ViewStub是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件。可以为ViewStub指定一个布局,在Inflate布局的时候,只有ViewStub会被初始化,然后当ViewStub被设置为可见的时候,或是调用了ViewStub.inflate()的时候,ViewStub所向的布局就会被Inflate和实例化,然后ViewStub的布局属性都会传给它所指向的布局。这样,就可以使用ViewStub来方便的在运行时,要还是不要显示某个布局。1. ViewStub只能Inflate一次,之后ViewStub对象会被置为空。按句话说,某个被ViewStub指定的布局被Inflate后,就不会够再通过ViewStub来控制它了。2. ViewStub只能用来Inflate一个布局文件,而不是某个具体的View,当然也可以把View写在某个布局文件中。28、 Activity的四种启动模式?standard: 标准模式,一调用 startActivity()方法就会产生一个新的实例。singleTop: 如果已经有一个实例位于 Activity 栈的顶部时, 就不产生新的实例, 而只是调用Activity 中的 newInstance()方法。如果不位于栈顶,会产生一个新的实例。singleTask: 会在一个新的 task 中产生这个实例,以后每次调用都会使用这个,不会去产生 新的实例了。singleInstance: 这个跟 singleTask 基本上是一样, 只有一个区别: 在这个模式下的 Activity实例所处的 task 中,只能有这个 activity实例,不能有其他的实例。29、 请介绍下AsyncTask的内部实现,适用的场景是?AsyncTask内部也是Handler机制来完成的,只不过Android提供了执行框架来提供线程池来执行相应地任务,因为线程池的大小问题,所以AsyncTask只应该用来执行耗时时间较短的任务,比如HTTP请求,大规模的下载和数据库的更改不适用于AsyncTask,因为会导致线程池堵塞,没有线程来执行其他的任务,导致的情形是会发生AsyncTask根本执行不了的问题。30、 介绍下实现一个自定义view的基本流程1、自定义View的属性 编写attr.xml文件2、在layout布
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 三基基础知识培训意义课件
- 高级领导决策技能面试题目及答案精 编
- 小儿骨科髋关节脱位课件
- 三八妇女节课件
- 初中书面表达主题分类训练10篇-文学艺术
- 大学生母亲节活动主题策划方案
- 大学生会计顶岗毕业实习报告
- 大专生毕业自我鉴定总结
- 地下停车位租赁的简单协议书
- 期货从业资格之期货投资分析考前冲刺测试卷讲解带答案详解(精练)
- 非战争军事行动中的后勤保障工作
- 金蝶K3供应链操作手册
- 高泌乳素症患者的护理
- 中国慢性阻塞性肺疾病基层诊疗指南(2024年)解读
- 电缆中间接头防火整改方案
- 2025届新高考数学一二轮复习备考建议与做法 课件
- 合作试验协议
- 全国高中生物奥林匹克竞赛试题
- 配电房安全管理培训
- GB 44263-2024电动汽车传导充电系统安全要求
- QB/T 2660-2024 化妆水(正式版)
评论
0/150
提交评论