您好,登录后才能下订单哦!
回想起前年左右,自己去社招的时候,一连串下来问了好多现在都是历历在目。回想起以前才觉得纸上得来终觉浅,绝知此事要躬行
所有的面试题答案并不是百分百的标准,要靠你自己的感悟和有自己的想法,才能独树一帜脱颖而出的。所有仅供参考
所有的都在这个PDF中有所汇总,983页花了几十个小时整理出来的。还是比较全面的有Android,Java小知识,到性能优化.线程.View.OpenCV.NDK.大厂面试,算法等等,大家可以联系我看看对自身有没有用
(更多完整项目下载。未完待续。源码。图文知识后续上传github。)
可以联系我获取完整PDF
(VX:mm14525201314)
Mockito;
注意: 单元测试不适合测试复杂的 UI 交互事件
Gradle
自动化测试、机型适配测试等
首先要了解 Java 四种引用类型的场景和使用(强引用、软引用、弱引用、虛引用)
SoftReference
对象是用来保存软引用的,但它同时也是一个 Java 对象,所以当软引用对象被回收之后,虽然这个 SoftReference
对象的 get 方法返回null,但 SoftReference
对象本身并不是 null,而此时这个 SoftReference
对象已经不再具有存在的价值,需要一个适当的清除机制,避免大量SoftReference
对象带来的内存泄露因此,Java 提供 ReferenceQueue
来处理引用对象的回收情况。当 SoftReference
所引用的对象被 GC 后,JVM 会先将 softReference
对象添加到ReferenceQueue
这个队列中。当我们调用 ReferenceQueue
的 的 poll() 方法,如果这个队列中不是空队列,那么将返回并移除前面添加的那个Reference
对象
public static void main(String[] args) throws InterruptedException {
//假设当前JVM内存只有8m
Person person = new Person( "/K=" );
ReferenceQueue Person> queue = new ReferenceQueue>( );
Sof tReference Person> softReference = new SoftReference<Person>(person, queue );
реrѕоn = null;// 去掉强引用, new Person ( "/K=" );的这个对象只有软引用了
Person anotherPerson = new Person( "/L=" )//没有足够的空间同事保留两个Person对象,所以触发GC机制
Thread.sleep(1000);
Sys tem. err . println( "软引用的对象 ------" > softReference.get( ));
Reference softPollRef = queue . poll( );
if (softPollRef != null) f
System.err.println( " SoftReference对象中保存的软引用对象已经被GC,准备清理SoftReference对象");
//清理softReference
}
}
CERT.SF
和 CERT.RSA
签名文件以及 MANIFEST.MF
清单文件。AssetManager
对象检索的应用资源。resources.arsc
。armeabi
armeabi-v7a
, arm64-v8a
, x86
, x86_64
,和mips
。resources.arsc
: 包含已编译的资源。该文件包含res/values/ 文件夹所有配置中的 XML 内容。打包工具提取此 XML 内容,将其编译为二进制格式,并将内容归档。此内容包括语言字符串和样式,以及直接包含在resources.arsc8
文件中的内容路径 ,例如布局文件和图像。Dalvik / ART
虚拟机可理解的X DEX 文件格式编译的类。AndroidManifest.xml
: 包含核心 Android 清单文件。该文件列出应用程序的名称,版本,访问权限和引用的库文件.该文件使用 Android 的二进制XML 格式。lib
、class.dex
和 res 占用了超过 90%的空间,所以这三块是优化 Apk
大小的重点(实际情况不唯一)图片文件压缩是针对 jpg
和 png
格式的图片。我们通常会放置多套不同分辨率的图片以适配不同的屏幕,这里可以进行适当的删减。在实际使用中,只保留一到两套就足够了(保留一套的话建议保留xxhdpi
,两套的话就加上 hdpi
),然后再对剩余的图片进行压缩(jpg
采用优图压缩,png
尝试采用pngquant
压缩)
buildTypes {
release {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile("proguard-android. txt"),’proguard-rules.pro’
}
}
shrinkResources
为 true 表示移除未引用资源,和代码压缩协同工作。minifyEnabled
为 true 表示通过 ProGuard
启用代码压缩,配合 proguardFiles
的配置对代码进行混淆并移除未使用的代码。apk
的同时,也提升了安全性。
armeabi
、armeabi-v7a
和 x86
这几种类型,这里可以只保留 armeabi
或 armeabi-v7a
的其中一个就可以了,实际上微信等主流 app 都是这么做的。build.gradle
直接配置即可,NDK
配置同理
defaultConfig {
ndk {
abiFilters 'armeabi'
}
}
插件化是指将 APK
分为 宿主和 插件的部分。把需要实现的模块或功能当做一个独立的提取出来,在 APP 运行时,我们可以动态的 载入或者 替换插件部分,减少 宿主的规模
而 热修复则是从修复 bug 的角度出发,强调的是在不需要二次安装应用的前提下修复已知的 bug。
Android 中常用的两种类加载器, DexClassLoader
和 PathClassLoader
,它们都继承于BaseDexClassLoader
,两者 区别在于PathClassLoader
只能加载 内部存储目录dex/jar/apk
文件。DexClassLoader
支持加载 指定目录(不限于内部)的 dex/jar/apk
文件
通过给插件 apk
生成相应的 DexClassLoader
便可以访问其中的类,可分为单 DexClassLoader
和多DexClassLoader
两种结构。
ClassLoader
机制,主工程引用插件中类需要先通过插件的 ClassLoader
加载该类再通过 反ClassLoader
机制,主工程则可以 直接通过类名去访问插件中的类。该方式有个弊端,若两个不同的插件工程引用了一个库的不同版本,则程序可能会出错。
原理在于通过反射将插件 apk
的路径加入AssetManager
中并创建 Resource
对象加载资源,有两种处理方式:
addAssetPath
时加入所有插件和主工程的路径;由于 AssetManager
中加入了所有插件和主工程的路径,因此生成的Resource
可以同时访问插件和主工程的资源。但是由于主工程和各个插件都是独立编译的,生成的资源 id 会存在相同的情况,在访问时会产生资源冲突。apk
路径,各个插件的资源是互相隔离的,不过如果想要实现资源的共享,必须拿到对应的 Resource
对象。
引入组件化的原因: 项目随着需求的增加规模变得越来越大,规模的增大导致了各种业务错中复杂的交织在一起,每个业务模块之间,代码没有约束,带来了代码边界的模糊,代码冲突时有发生, 更改一个小问题可能引起一些新的问题, 牵一发而动全身,增加一个新需求,需要熟悉相关的代码逻辑,增加开发时间
组件化开发流程就是把一个功能完整的 App 或模块拆分成多个子模块( Module ),每个子模块可以 独立编译运行,也可以任意组合成另一个新的 App 或模块,每个模块即不相互依赖但又可以相互交互,但是最终发布的时候是将这些组件合并统一成一个 apk,遇到某些特殊情况甚至可以升级或者
ARouter
配合架构中的 公共服务(CommonService
) 实现:
CommonService
) 中声明 Service
接口 (含有需要被调用的自定义方法), 然后在自己的模块中实现这个 Service 接口, 再通过 ARouter API
暴露实现类。ARouter
的 API 拿到这个Service
接口(多态持有, 实际持有实现类), 即可调用 Service
接口中声明的自定义方法, 这样就可以达到模块之间的交互。AndroidEventBus
其独有的Tag, 可以在开发时更容易定位发送事件和接受事件的代码, 如果以组件名来作为 Tag 的前缀进行分组, 也可以更好的统一管理和查看每个组件的事件, 当然也不建议大家过多使用 EventBus
。RouterHub
存在于基础库, 可以被看作是所有组件都需要遵守的通讯协议, 里面不仅可以放路由地址常量, 还可以放跨组件传递数据时命名的各种 Key 值,再配以适当注释, 任何组件开发人员不需要事先沟通只要依赖了这个协议, 就知道了各自该怎样协同工作, 既提高了效率又降低了出错风险, 约定的东西自然要比口头上说强。RouterHub
中, 太麻烦了, 也可以在每个组件内部建立一个私有 RouterHub
, 将不需要跨组件的路由地址放入私有 RouterHub
中管理, 只将需要跨组件的路由地址放入基础库的公有 RouterHub
中管理, 如果您不需要集中管理所有路由地址的话, 这也是比较推荐的一种方式。
ARouter
路由原理:ARouter
维护了一个路由表 Warehouse,其中保存着全部的模块跳转关系,ARouter
路由跳转实际上还是调用了 startActivity
的跳转,使用了原生的Framework 机制,只是通过 apt 注解的形式制造出跳转规则,并人为地拦截跳转和设置跳转条件
Hook 是一种用于 改变 API执行结果的技术,能够将系统的API 函数执行 重定向(应用的 触发事件和 后台逻辑处理是根据事件流程一步步地向下执行。而 Hook 的意思,就是在事件传送到终点前截获并监控事件的传输,像个钩子钩上事件一样,并且能够在钩上事件时,处理一些自己特定的事件,例如逆向破解 App)
插桩是以静态的方式修改第三方的代码,也就是从编译阶段,对源代码(中间代码)进行编译,而后重新打包,是静态的篡改; 而 Hook则不需要再编译阶段修改第三方的源码或中间代码,是在运行时通过反射的方式修改调用,是一种 动态的篡改
作用: 通过宽测量值 widthMeasureSpec
和高测量值heightMeasureSpec
决定 View 的大小
组成: 一个 32 位 int 值,高 2 位代表 SpecMode
(测量模式),低 30 位代表 SpecSize( 某种测量模式下的规格大小)。
三种模式:
SpecSize
。对应 LyaoutParams
中的match_parent 或具体数值。SpecSize
,View 的大小不能大于这个值。对应LayoutParams
中的 wrap_content。图片加载库:Fresco 丶Glide 、o Picasso 等
AnimatorSet
正是通过playTogether()
、playSequentially()
、animSet.play().with()
、before()
、after()
这些方法来控制多个动画协同工作,从而做到对动画播放顺序的精确控制// animation主要用于tween动画
//根据资源得到动画
Animation roitateAnimation = AnimationUtils.loadAnimation(this,R.anim.rotata_anim);
//播放动画完成之后,保留动画最后的状态
rotateAnimation.setFillAfter(true);
//播放动画
btnRotate.startAnimation(rotateAnimation);
// animator主要用于属性动画
objectAnimator animator = objectanimator.ofFloat(textview,"alpha,1f,0f,1f);
animator.setDuration(5000);
animator,start();
AnimatorSet animatorSet = new AnimatorSet();
//移动
objectAnimator ty = object Animator.ofFloat(btn,"translationY",0,300);
ty.setDuration(1000);
//旋转
objectAnimator ty = objectAnimator.ofFloat(btn, "rotationY", 0,1080);
//透明度
objectAnimator alpha = objectAnimator.ofFloat(btn, "alpha", 1,0,0.5f,1);
//缩放
objectAnimator sx = objectAnimator.ofFloat(btn, "scaleX",1,0.5f);
//一起播放
// animatorSet.playTogether(items);
animatorSet.play(ry),with(sx).after(ty).before(alpha);
animatorSet.start();
请查看完整的PDF版
(更多完整项目下载。未完待续。源码。图文知识后续上传github。)
可以联系我获取完整PDF
(VX:mm14525201314)
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。