一次违反常规的大厂OPPO面试经历(文末有面试答案领取)

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注Android)
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

正文

3.final关键字的用法?
final 可以修饰类、变量和方法。修饰类代表这个类不可被继承。修饰变量代表此变量不可被改变。修饰方法表示此方法不可被重写 (override)。
4.死锁是怎么导致的?如何定位死锁
某个任务在等待另一个任务,而后者又等待别的任务,这样一直下去,直到这个链条上的任务又在等待第一个任务释放锁。这得到了一个任务之间互相等待的连续循环,没有哪个线程能继续。这被称之为死锁。当以下四个条件同时满足时,就会产生死锁:
(1) 互斥条件。任务所使用的资源中至少有一个是不能共享的。
(2) 任务必须持有一个资源,同时等待获取另一个被别的任务占有的资源。
(3) 资源不能被强占。
(4) 必须有循环等待。一个任务正在等待另一个任务所持有的资源,后者又在等待别的任务所持有的资源,这样一直下去,直到有一个任务在等待第一个任务所持有的资源,使得大家都被锁住。
要解决死锁问题,必须打破上面四个条件的其中之一。在程序中,最容易打破的往往是第四个条件。
关于如何手写死锁和定位方法,可参考这篇博客。
5.数据库如何进行升级?SQLite增删改查的基础sql语句?

/**     * Create a helper object to create, open, and/or manage a database.     * This method always returns very quickly.  The database is not actually     * created or opened until one of {@link #getWritableDatabase} or     * {@link #getReadableDatabase} is called.     *     * @param context to use to open or create the database     * @param name of the database file, or null for an in-memory database     * @param factory to use for creating cursor objects, or null for the default     * @param version number of the database (starting at 1); if the database is older,     *     {@link #onUpgrade} will be used to upgrade the database; if the database is     *     newer, {@link #onDowngrade} will be used to downgrade the database     */    public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) {        this(context, name, factory, version, null);    }    public SQLiteDatabase getWritableDatabase() {        synchronized (this) {            return getDatabaseLocked(true);        }    }  private SQLiteDatabase getDatabaseLocked(boolean writable) {      …      db.beginTransaction();      try {              if (version == 0) {                   onCreate(db);              } else {                   if (version > mNewVersion) {                         onDowngrade(db, version, mNewVersion);                   } else {                         onUpgrade(db, version, mNewVersion);                   }              }               db.setVersion(mNewVersion);                db.setTransactionSuccessful();              } finally {                 db.endTransaction();              }  }

在SQLiteOpenHelper的构造函数中,包含了一个version的参数。这个参数即是数据库的版本。 所以,我们可以通过修改version来实现数据库的升级。 当version大于原数据库版本时,onUpgrade()会被触发,可以在该方法中编写数据库升级逻辑。具体的数据库升级逻辑示例可参考这里。
常用的SQL增删改查:

增:INSERT INTO table_name (列1, 列2,…) VALUES (值1, 值2,….)
删: DELETE FROM 表名称 WHERE 列名称 = 值
改:UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值
查:SELECT 列名称(通配是*符号) FROM 表名称

ps:操作数据表是:ALTER TABLE。该语句用于在已有的表中添加、修改或删除列。
ALTER TABLE table_name ADD column_name datatype
ALTER TABLE table_name DROP COLUMN column_name
ALTER TABLE table_name_old RENAME TO table_name_new

Android方面

1.Broadcast的分类?有序,无序?粘性,非粘性?本地广播?

  • 广播可以分为有序广播、无序广播、本地广播、粘性广播。其中无序广播通过sendBroadcast(intent)发送,有序广播通过sendOrderedBroadcast(intent)发送。

  • 有序广播。
    (1) 有序广播可以用priority来调整优先级   取值范围-1000~+1000,默认为0,数值越大优先级越高,优先级越高越优先获得广播响应。
    (2) abortBroadcast()可来终止该广播的传播,对更低优先级的屏蔽,注意只对有序广播生效。
    (3) 有序广播在传播数据中会发生比如setResultData(),getResultData(),在传播过程中,可以从新设置数据

  • 关于本地广播,可以查看这篇文章。总的来说,本地广播是通过LocalBroadcastManager内置的Handler来实现的,只是利用了IntentFilter的match功能,至于BroadcastReceiver 换成其他接口也无所谓,顺便利用了现成的类和概念而已。在register()的时候保存BroadcastReceiver以及对应的IntentFilter,在sendBroadcast()的时候找到和Intent对应的BroadcastReceiver,然后通过Handler发送消息,触发executePendingBroadcasts()函数,再在后者中调用对应BroadcastReceiver的onReceive()方法。

  • 粘性消息:粘性消息在发送后就一直存在于系统的消息容器里面,等待对应的处理器去处理,如果暂时没有处理器处理这个消息则一直在消息容器里面处于等待状态,粘性广播的Receiver如果被销毁,那么下次重建时会自动接收到消息数据。(在 android 5.0/api 21中deprecated,不再推荐使用,相应的还有粘性有序广播,同样已经deprecated)

2.Android中的事件传递机制?
当我们的手指触碰到屏幕,事件是按照Activity->ViewGroup->View这样的流程到达最终响应触摸事件的View的。而在事件分发过程中,涉及到三个最重要的方法:dispatchTouchEvent()、onInterceptTouchEvent()、onTouchEvent。我们的手指触摸到屏幕的时候,会触发一个Action_Down类型的事件,当前页面的Activity会首先做出相应,也就是说会走到Activity的dispatchTouchEvent()方法内。在这个方法内部有下面两个逻辑:

  • 调用getWindow.superDispatchTouchEvent()。

  • 如果上一步返回true,则直接返回true;否则return自己的onTouchEvent()。显然,当getWindow.superDispatchTouchEvent()返回true,表示当前事件已经被消费掉,无需调用onTouchEvent;否则代表事件并没有被处理,因此需要调用Activity的onTouchEvent进行处理。
    我们都知道,getWindow()返回的是PhoneWindow,因此这句代码本质上调用了PhoneWindow中的superDispatchTouchEvent()。而后者实际上调用了mDecor.superDispatchTouchEvent(event)。这个mDecor也就是DecorView,它是FrameLayout的一个子类。在DecorView中的superDispatchTouchEvent(event)中调用的是super.dispatchTouchEvent()。因此,本质上调用的是ViewGroup的dispatchTouchEvent()。

到这里,事件已经从Activity传递到ViewGroup了。接下来我们分析ViewGroup。
在ViewGroup的dispatchTouchEvent()中逻辑大致如下:

  • 通过onInterceptTouchEvent()判断当前ViewGroup是否拦截,默认的ViewGroup都是不拦截的;

  • 如果拦截,则return自己的onTouchEvent();

  • 如果不拦截,则根据child.dispatchTouchEvent()的返回值判断。如果返回true,则return true;否则return自身的onTouchEvent(),在这里实现了未处理事件的向上传递。

通常情况下,ViewGroup的onInterceptTouchEvent()都返回false,表示不拦截。这里需要注意的是事件序列,比如Down事件、Move事件…Up事件,从Down到Up是一个完整的事件序列,对应着手指从按下到抬起这一系列事件,如果ViewGroup拦截了Down事件,那么后续事件都会交给这个ViewGroup的onTouchEvent。如果ViewGroup拦截的不是Down事件,那么会给之前处理这个Down事件的View发送一个Action_Cancel类型的事件,通知子View这个后续的事件序列已经被ViewGroup接管了,子View恢复之前的状态即可。
这里举一个常见的例子:在一个 Recyclerview 中有很多的 Button,我们首先按下了一个 button,然后滑动一段距离再松开,这时候 Recyclerview 会跟着滑动,并不会触发这个 button 的点击事件。这个例子中,当我们按下 button 时,这个 button 接收到了 Action_Down 事件,正常情况下后续的事件序列应该由这个 button处理。但我们滑动了一段距离,这时  Recyclerview 察觉到这是一个滑动操作,拦截了这个事件序列,走了自身的 onTouchEvent()方法,反映在屏幕上就是列表的滑动。而这时 button 仍然处于按下的状态,所以在拦截的时候需要发送一个 Action_Cancel 来通知 button 恢复之前状态。
事件分发最终会走到View的dispatchTouchEvent()中。在View的dispatchTouchEvent()中没有onInterceptTouchEvent(),这里很容易理解,View没有child,也就不存在拦截。View的dispatchTouchEvent()直接return了自己的onTouchEvent()。如果onTouchEvent()返回true代表事件被消费,否则未消费的事件会向上传递,直到有View处理了事件或一直没有消费,最终回到Activity的onTouchEvent()终止。
有时候会有人混淆onTouchEvent和onTouch。首先,这两个方法都在View的dispatchTouchEvent()中:

  • 如果touchListener不为null,并且这个View是enable的,而且onTouch返回true,都满足时直接return true,走不到onTouchEvent()方法。

  • 否则,就会触发onTouchEvent()。因此onTouch优先于onTouchEvent获得事件处理权。

最后附上流程图总结:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

参考:https://juejin.im/entry/58df5b33570c35005798493c
https://juejin.im/post/5b8f15e26fb9a01a031b12d9#heading-3

3.Handler的原理?
与Handler密切相关的还有Message、MessageQueue、Looper。

  • Message。Message有两个关键的成员变量:target、callback:
    (1) target。就是发送消息的Handler
    (2) callback。调用Handler.post(Runnable)时传入的Runnable类型的任务。post事件的本质也是创建了一个Message,将我们传入的这个runnable赋值给创建的Message的callback这个成员变量。

  • MessageQueue。消息队列用于存放消息,其中重点关注next()方法,它会返回下一个待处理的消息。

  • Looper。Looper消息轮询器其实是连接Handler和消息队列的核心。想要在一个线程中创建一个Handler,首先要通过Looper.prepare()创建Looper,之后还得调用Looper.loop()开启轮询。
    (1) prepare()。这个方法做了两件事:首先通过ThreadLocal.get()获取当前线程中的Looper,如果不为空则抛出RuntimeException。否则创建Looper,并通过ThreadLocal.set(looper)将当前线程与刚刚创建的Looper绑定。值得注意的是,上面的消息队列的创建其实就是发生在Looper的构造函数中。
    (2)loop()。这个方法开启了整个事件机制的轮询。其本质是开启一个死循环,不断地通过MessageQueue的next()方法获取消息msg。拿到消息后会调用msg.target.dispatchMessage()来做处理。综上也就是调用handler.dispatchMessage()。

  • Handler。Handler重点在于发送消息和处理消息。
    (1)发送消息。其实发送消息除了 sendMessage 之外还有 sendMessageDelayed 和 post 以及 postDelayed 等等不同的方式。但它们的本质都是调用了 sendMessageAtTime。在 sendMessageAtTime 这个方法中调用了 enqueueMessage。在 enqueueMessage 这个方法中做了两件事:通过 msg.target = this 实现了消息与当前 handler 的绑定。然后通过 queue.enqueueMessage 实现了消息入队。
    (2)处理消息。 消息处理的核心其实就是dispatchMessage()这个方法。这个方法里面的逻辑很简单,先判断 msg.callback 是否为 null,如果不为空则执行这个 runnable。如果为空则会执行我们的handleMessage方法。

4.ANR出现的情况有几种? 怎么分析解决ANR问题?
ANR(Application Not responding)。Android中,主线程(UI线程)如果在规定时内没有处理完相应工作,就会出现ANR。具体来说,ANR会在以下几种情况中出现:
(1) 输入事件(按键和触摸事件)5s内没被处理
(2) BroadcastReceiver的事件(onRecieve方法)在规定时间内没处理完(前台广播为10s,后台广播为60s)
(3) service 前台20s后台200s未完成启动
(4) ContentProvider的publish在10s内没进行完

分析ANR问题,需要结合Log以及trace文件。具体分析流程,可参照以下两篇文章:
https://www.jianshu.com/p/fa962a5fd939
https://blog.csdn.net/droyon/article/details/51099826

5.内存泄露的场景有哪些?内存泄漏分析工具使用方法?
常见的内存泄露有:

  • 单例模式引起的内存泄露。

  • 静态变量导致的内存泄露。

新的开始

改变人生,没有什么捷径可言,这条路需要自己亲自去走一走,只有深入思考,不断反思总结,保持学习的热情,一步一步构建自己完整的知识体系,才是最终的制胜之道,也是程序员应该承担的使命。

《系列学习视频》
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

《系列学习文档》

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

《我的大厂面试之旅》

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

Android)**
[外链图片转存中…(img-M5t7Jh6P-1713085912570)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《代码随想录知识星球精华-大厂面试八股文v1.1.pdf》是一份介绍八股文的面试指南,针对大厂面试常见题型进行分类,以及给出相应的解答思路。这份资料具有很高的参考价值,在为即将面试的求职者提供指引的同时,也可以让读者对八股文的思维框架和策略有更好的了解。 这份资料主要包括面试题目的主题分类,如动态规划、字符串、树等,每个分类下又相应给出了典型的问题,如“最长公共子序列”、“二叉树的层次遍历”等等。对于每个问题,都给出了具体的思路指导和代码模板,许多题目给出了多种不同的解法,这些解法包括时间复杂度和空间复杂度的优化。 这份资料对于求职者来说,意义重大。在面试中,对于某些问题我们可能没有完全解决,但如果有了这份资料,我们在面试中也会有一个清晰的思考框架和即时可用的代码模板。此外,这份资料同样适用于对算法和数据结构感兴趣的开发者和工程师,对于自学和提高都有帮助。 总之,《代码随想录知识星球精华-大厂面试八股文v1.1.pdf》是一个非常实用的参考材料,它是广大求职者和程序员不可或缺的工具,值得一读。 ### 回答2: 《代码随想录知识星球精华-大厂面试八股文v1.1.pdf》是一份由知名博主“代码随想”的知识星球推出的热门资料。该资料主要介绍了大厂面试中常见的八股文,包括但不限于动态规划、双指针、贪心算法、字符串操作等。 通过学习该资料,可以系统地学习和掌握各种常见的算法和数据结构,有助于提高自己的代码能力和面试竞争力。此外,资料还给出了一些实际的面试题目例子,对于准备去大厂面试的人来说,是一份非常实用的资料。 当然,要想真正掌握这些算法和数据结构,需要自己的不断练习和实践。只有在解决实际问题的过程中,才能真正体会到这些算法和数据结构的作用和优越性。 总之,该资料对于想要深入了解算法和数据结构、提高面试竞争力的人来说是一份值得推荐的优秀资料。 ### 回答3: 代码随想录知识星球精华-大厂面试八股文v1.1.pdf是一份关于大厂面试八股文的精华资料,它收集整理了各个大厂面试中常见的八股文题目和解题思路,对于准备求职或者升职的程序员来说是一份非常有价值的资料。 该资料中涵盖了常见的算法、数据结构、操作系统、计算机网络、数据库、设计模式等知识点,每个知识点都有详尽的讲解和相应的面试题目,可以帮助面试者全面了解每个知识点的考察方向和难点。 此外,该资料还提供了八股文的解题思路和解题方法,强调了实战经验和面试技巧,对于提高面试的成功率也是非常有帮助的。 总之,代码随想录知识星球精华-大厂面试八股文v1.1.pdf是一份非常实用的面试资料,它帮助面试者深入了解各个知识点的考察方向和难点,提高了应对面试的能力和成功率,对于准备求职或者升职的程序员来说是一份不可或缺的资料。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值