我是从小公司跳出来的,最终入职OPPO,说实话这段时间的经历让我深深地感受到,我们为跳槽做的一些临时抱佛脚的提升跟那些大佬的沉淀比起来太渺小了。我们都知道找资料学习、刷面试题,但也许只能应付这一次的面试,后面还是会技术发愁,那些短时间背下来的东西迟早会忘掉, 大家还是做好长期提升自己的准备,好好沉淀的东西最后才是属于自己的。
说说当时的面试过程,我是内推获得的面试机会,很感谢当时帮我内推的兄弟,总共三轮面试,两轮技术,一轮HR面,当天面试结束。
我10:10分到的公司,10:30开始面试,第一轮面试将近一个小时,聊的点我基本上都答得上来,自我感觉良好。然后面试官让我等一下,他去叫他们老大来给我二面,我等了有二十几分钟吧,二面有一个多小时,这次问的比较深,有些地方答的有些嗑吧,总体来说我自己是满意的。HR面约到下午了,整个流程下来每轮面试官都让人感觉很不错,我自己做的准备也让我面试感觉下来很爽。
我把面试遇到过的以及自己学习用到过相关内容都整理到一起了,方便自己进行复盘和后续的查漏补缺:
一、 Java基础
11 静态内部类和非静态内部类的比较
12 多态的理解与应用
13 java方法的多态性理解
14 java中接口和继承的区别
15 线程池的好处,详解,单例(绝对好记)
16 线程池的优点及其原理
17 线程池的优点(重点)
18 为什么不推荐通过Executors直接创建线程池
19 不怕难之BlockingQueue及其实现
110 深入理解ReentrantLock与Condition
111 Java多线程:线程间通信之Lock
112 Synchronized 关键字原理
113 ReentrantLock原理
114 HashMap中的Hash冲突解决和扩容机制
114 Java并发
115 Java虚拟机
116 JVM常见面试题
117 JVM内存结构
118 类加载机制/双亲委托
二、 Android基础
21 Activity知识点(必问)
22 Fragment知识点
23 Service知识点
24 Intent知识点
25 数据存储
三、UI控件篇
31 屏幕适配
32 主要控件优化
33 事件分发与嵌套滚动
34 动态化页面构建方案
四、网络通信篇
41 网络协议
五、架构设计篇
51 MVP架构设计
52 组件化架构
六、性能优化篇
61 启动优化
62 内存优化
63 绘制优化
64 安装包优化
七、源码流程篇
71 开源库源码分析
72 Glide源码分析
73 day 20 面试题:Glide面试题
74 聊一聊关于Glide在面试中的那些事
75 面试官:简历上如果写Glide,请注意以下几点…
76 Glide OOM问题解决方法汇总
77 LeakCanary源码分析
78 Ok> 上一篇 > 在前面的课程中,随着对Android体系的了解,已经可以进行正常的Android应用开发了。在Android开发中,同其他工程开发一样,也经常使用一些提高效率的框架,本文我们做一个对比。这些框架,既包括:网络请求框架、也包括加载库框架、还包括数据库 *** 作等一些框架,总之,了解和熟悉这些框架,会对自己的开发效率有很大的提升和帮助。 网络请求框架 1、ok> 在前文的学习中,我们已经了解过ok> 2、Retrofit 介绍 Retrofit是一个很不错的网络请求库,该库是square开源的另外一个库,之前的ok> Retrofit是基于Ok> A type-safe REST client for Android and Java 该网络框架在github上的地址如下:> 要求 Retrofit支持的> 依赖 使用Retrofit库,和其他库一样,首先需要设置依赖,依然是在buildgradle文件中设置依赖: //添加retrofit库依赖 implementation ‘comsquareupretrofit2:retrofit:210’ //添加gson转换器 implementation ‘comsquareupretrofit2:converter-gson:210’ 使用 通过一个例子,我们可以来演示该框架的使用步骤: 1、定义请求接口,即程序中都需要什么请求 *** 作 public interface > / 获取头条新闻 @param type 新闻类型 @param key apiKey @return / @GET(“toutiao/index”) Call getNewsList(@Query(“type”) String type, @Query(“key”) String key); } 2、实例化Retrofit对象,使用的Builder的模式创建,如下代码所示: Retrofit retrofit = new RetrofitBuilder() baseUrl(ConstantsBASE_API) addConverterFactory(GsonConverterFactorycreate()) build(); 注意,这里设置结构体转换器,是可以直接把网络请求回来的数据转换为Java结构体,这里设置的Gson解析器,因此要引入相应的转换器支持库。 3、得到接口对象,自己创建的全局的接口对象,并调用相应的接口,得到一个类似于请求Call对象。如下所示: > Call newsListCall = > 4、加入到请求队列中,并设置回调方法: newsListCallenqueue(new Callback() { @Override public void onResponse(Call call, Response response) { //网络请求成功的回调方法 List list = ArraysasList(responsebody()resultdata); Logi(“TAG”, “请求成功:” + StringvalueOf(listsize())); NewListAdapter adapter = new NewListAdapter(RetrofitActivitythis); adaptersetmData(list); mRecyclerViewsetAdapter(adapter); } @Override public void onFailure(Call call, Throwable throwable) { //网络请求失败的回调方法 Logi(“TAG”, “请求失败:” + throwablegetMessage()); } }); 其他界面 *** 作和之前的Android中的内容一致。 3、RxJava 简单来说,用来处理事件和异步任务,在很多语言上都有实现,RxJava是Rx在Java上的实现。 原理 RxJava最基本的原理是基于观察者模式来实现的。通过Obserable和Observer的机制,实现所谓响应式的编程体验。 特点 RxJava在编程中的实现就是一种链式调用,做了哪些 *** 作,谁在前谁在后非常直观,逻辑清晰,代码维护起来非常轻松。 RxJava也是一个在github上的库,github> 基于此,还有一个RxAndroid,github地址如下:> RxJava和RxAndroid的关系 RxAndroid是RxJava的一个针对Android平台的扩展,主要用于 Android 开发。 基本概念 RxJava 有四个基本概念: Observable:可观察者,即被观察者Observer:观察者subscribe:订阅事件 这四个概念之间的逻辑关系是:Observable和Observer通过subscribe方法实现订阅关系,从而Observable可以在需要的时候发出事件来通知Observer。 事件 RxJava 的事件回调方法主要包含以下几个: onNext:普通的事件onCompleted> 在开发时,本地数据库可以起到缓存数据和存储业务数据的作用,随着技术的成熟,不断推出了有很多关于数据库的 *** 作框架。比较常见的数据库 *** 作框架有诸如:GreenDao,OrmLite 和 ActiveAndroid,DBFlow等。 GreenDAO GreenDAO是一个开源的 Android ORM(“对象/关系映射”),通过 ORM(称为“对象/关系映射”),在我们数据库开发过程中节省了开发时间! GreenDao的官方文档地址如下:> GreenDao的作用 通过 GreenDao,我们可以更快速的 *** 作数据库,我们可以使用简单的面相对象的API来存储,更新,删除和查询 Java 对象。这款数据库 *** 作框架的特点是: 高性能,在官方的统计数据中,GreenDao在GreenDao,OrmLite 和 ActiveAndroid三个框架中,读、写、更新 *** 作效率均表现第一。易于使用的强大 API,涵盖关系和连接。内存消耗较小。安全:greenDAO 支持 SQLCipher> GreenDao 的核心类有三个:分别是: DaoMaster:保存数据库对象(SQLiteDatabase)并管理特定模式的 DAO 类(而不是对象)。它有静态方法来创建表或删除它们。它的内部类 OpenHelper 和DevOpenHelper 是 SQLiteOpenHelper 实现,它们在 SQLite 数据库中创建模式。DaoSession:管理特定模式的所有可用 DAO 对象,您可以使用其中一个getter方法获取该对象。DaoSession 还提供了一些通用的持久性方法,如实体的插入,加载,更新,刷新和删除。XXXDao:数据访问对象(DAO)持久存在并查询实体。对于每个实体,greenDAO 生成DAO。它具有比 DaoSession 更多的持久性方法。Entities:可持久化对象。通常, 实体对象代表一个数据库行使用标准 Java 属性(如一个POJO 或 JavaBean )。 使用 按照官方的文档和github上的说明可以实现greendao的使用。 首先进行的是依赖,对于greenDao,有两个地方需要设置,分别是项目根目录中的 buildgradle,还有module中的buildgradle。 classpath ‘orggreenrobot:greendao-gradle-plugin:330’ // add plugin 在项目根目录中的buildgradle目录中写这句话的意思是添加greenDao的插件。 在项目module中的buildgradle中也需要进行配置,有两个地方需要设置,如下图所示: apply plugin: ‘orggreenrobotgreendao> dependences{ implementation ‘orggreenrobot:greendao:320’ } 然后就可以使用了。 bean实体 可以在项目中创建自己业务需要的实体类,并通过注解来设置是实体类,字段约束等内容。然后点击Android Studio中的Make module,即可自动生成XXXDao代码,以此来方便开发者的 *** 作。生成的XXXDao类,不可修改和编辑,是自动生成的。 ORMLite ORMLite框架是另外一款Android开发中可以使用的数据库 *** 作框架。该框架的文档地址如下:> 该框架的文档准备的不是特别友好,此处不再赘述。 总结,所有的框架原理几乎都相差不大,只是 *** 作有所差异。 视图注入框架 在Android项目开发过程中,有太多的页面需要布局完成,同时在代码中需要些大量的findviewbyid的 *** 作,来实现控件的解析。于是就有人想能否轻松一些,解放双手节省时间,干一些其他有意义的事情,于是ButterKnife就来了。 ButterKnife是一个专注于Android系统的View注入框架,可以减少大量的findViewById以及setOnClickListener代码,可视化一键生成。 该项目在github上的地址如下:> 这个框架的优势也非常明显: 强大的View绑定和Click事件处理功能,简化代码,提升开发效率方便的处理Adapter里的ViewHolder绑定问题运行时不会影响APP效率,使用配置方便代码清晰,可读性强 使用 首先是设置依赖,在buildgradle> implementation ‘comjakewharton:butterknife:1021’ annotationProcessor ‘comjakewharton:butterknife-compiler:1021’ 需要注意,该框架要求Java环境18版本以上,SDK版本在26以上,因此在使用到的module中的buildgraldle文件中,还必须添加如下代码配置: apply plugin: ‘comjakewhartonbutterknife’ android{ //… compileOptions { sourceCompatibility JavaVersionVERSION_1_8 targetCompatibility JavaVersionVERSION_1_8 } //… } 另外,还必须在项目根目录中的buildgradle文件中,添加该框架的插件,如下图所示: dependences{ classpath ‘comjakewharton:butterknife-gradle-plugin:1021’ } 然后即可在代码中进行使用了。 在使用该框架的页面进行绑定诸如,如下所示代码: ButterKnifebind( this) ; 主要的功能 @BindView():控件id 注解,解放双手,不用再每个控件都写一遍findviewById@BindViews():多个控件id 的注解,括号内使用花括号包括多个id即可,中间用,分割开在Fragment中使用,绑定Fragment。@BindString():绑定字符串@BindArray:绑定数组@BindBitmap:绑定bitmap资源@OnClick、@OnLongClick:绑定点击事件和长按事件…还有很多 插件安装 如果是页面很复杂,一个一个写BindView也很费劲,在Android Studio中,可以安装一个ButterKnife的插件,安装该插件后,可以在Studio中直接将对应的布局中的所有控件均给自动生成。 注意,在进行自动生成时,鼠标要放在布局文件上。 注意事项 ButterKnife框架在使用时,要求的版本比较高,包括Java的版本也有限制。因此,如果计划在项目中使用,要提前做好预备工作,以防止对已有项目和业务带来不必要的麻烦,反而影响工作进度。
作为一个单工程撸到底的开发人员,想试着将项目进行组件化改造,说动就动。毕竟技术都是写出来的,看着文章感觉懂了,但是实际开发中还是能遇到各种各样的问题,开始搞起来。
一直使用单工程撸到底,项目越来越大导致出现了不少的问题:
将 一个程序按照其功能做拆分,分成相互独立的模块 ,以便于每个模块只包含与其功能相关的内容,比如 登录模块 、 首页模块 等等。
组件指的是单一的功能组件,如 登录组件 、 视频组件 、 支付组件 等,每个组件都可以以一个单独的 module 开发,并且可以单独抽出来作为 SDK 对外发布使用。可以说往往一个模块包含了一个或多个组件。
组件化基于可重用的目的,将应用拆分成多个独立组件,以 减少耦合 :
组件依赖关系是上层依赖下层,修改频率是上层高于下层。先上一张图:
基础公共模块,最底层的库:
这只是个大概,并不是说必须这样,可以按照自己的方式来。比如:你觉得基础组件比较多导致project里面的项目太多,那么你可以创建一个lib_base,然在lib_base里面再创建其他基础组件即可。
这样尽可能的减少变动项,当然这仅仅是个建议,看个人习惯吧。
因为咱们创建的是一个module,所以在AndridManifest中添加android:exported="true"属性可直接构建一个APK。下面咱们看看如何生成不同的工程类型。
在 AndroidStudio 开发 Android 项目时,使用的是 Gradle 来构建,具体来说使用的是 Android Gradle 插件来构建,Android Gradle 中提供了三种插件,在开发中可以通过配置不同的插件来构建不同的工程。
独立调试 :设置为 Application 插件。
集成调试 :设置为 Library 插件。
isDebug = true 独立调试
根据上面动态配制插件的经验,我们也需要在buildgradle中动态配制ApplicationId 和 AndroidManifest 文件。
有什么不同?咱们一起看看具体内容。
isDebug = true
isDebug = false
当我们需要进行插件版本、依赖库版本升级时,项目多的话改起来很麻烦,这时就需要我们对Gradle配置统一管理。如下:
具体内容
Android 中的界面跳转那是相当简单,但是在组件化开发中,由于不同组件式没有相互依赖的,所以不可以直接访问彼此的类,这时候就没办法通过显式的方式实现了。
所以在这里咱们采取更加灵活的一种方式,使用 Alibaba 开源的 ARouter 来实现。
文档介绍的蛮详细的,感兴趣的可以自己实践一下。这里做个简单的使用。
先在统一的 configgradl e添加版本等信息
因为所有的功能组件和业务组件都依赖lib_common,那么咱们先从lib_common开始配制
lib_common
其他组件(如collect)
你要跳转的 Activity
这里是用 module_main 的HomeFragment跳转至 module_collect 的CollectActivity界面,两个module中不存在依赖关系。 "/collect/CollectActivity" 在上面已注册就不多描述了。
效果如下:
这里是用 module_main 的MineFragment的Adapter跳转至 module_webview 的WebViewActivity界面,两个module中同样不存在依赖关系。
启动方
这里传了两个参数 url 和 name 到WebViewActivity,下面咱们看看WebViewActivity怎么接收。
接收方
上效果图:
搞定,更多高级玩法可自行探索。
W/ARouter::: ARouter::There is no route match the path
这里出现个小问题,配置注释都好好的,但是发送发无论如何都找不到设置好的Activity。尝试方案:
后来修改Activity名称好了。
界面跳转搞定了,那么数据传递怎么办,我在module_main中使用悬浮窗,但是需要判断这个用户是否已登录,再执行后续逻辑,这个要怎么办?这里我们可以采用 接口 + ARouter 的方式来解决。
在这里可以添加一个 componentbase 模块, 这个模块被所有的组件依赖 。
这里我们通过 module_main组件 中调用 module_login组件 中的方法来获取登录状态这个场景来演示。
lib_common
所有业务组件和功能组件都依赖lib_common,所以咱们直接在lib_common添加依赖即可
module_login
实现接口
运行结果:
本文介绍了组件化、组件分层、解决了组件的独立调试、集成调试、页面跳转、组件通信等。
其实会了这些后你基本可以搭建自己的组件化项目了。其实最大的问题还是分组分层、组件划分。这个就需要根据你的实际情况来设置。
本项目比较糙,后面会慢慢完善。比如添加Gilde、添加MMVK、添加Room等。
项目传送门
在开启混淆编译完成后,测试apk发现异常,通过日志分析发现使用ARouter跳转的Activity中,@Autowired标准的变量未注入成功,上github查看arouter文档,发现在app/proguard-rulespro添加一下规则就可以修复这个问题:
# ARouter
-keep public class comalibabaandroidarouterroutes{;}
-keep public class comalibabaandroidarouterfacade{;}
-keep class implements comalibabaandroidarouterfacadetemplateISyringe{;}
# 如果使用了 byType 的方式获取 Service,需添加下面规则,保护接口
-keep interface implements comalibabaandroidarouterfacadetemplateIProvider
# 如果使用了 单类注入,即不定义接口实现 IProvider,需添加下面规则,保护实现
-keep class implements comalibabaandroidarouterfacadetemplateIProvider
以上就是关于Android大厂面试经验分享(OPPO,字节,华为,阿里)全部的内容,包括:Android大厂面试经验分享(OPPO,字节,华为,阿里)、项目引用Kotlin与databinding,ARouter,Architecture Components冲突解决办法、29.ARouter组件互调原理等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)