日常积累

日常积累

查看依赖关系
bash gradlew -q app:dependencies >> a.txt
a.txt 在项目根目录

git设置远程依赖
git remote set-url origin https://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@github.com/moruoyiming/moruoyiming.github.io.git

查看包名下进程信息
adb shell ps | grep packagename

查看应用activity堆栈
adb shell dumpsys activity packagename

查看CERT.RSA就包含签名信息
keytool -printcert -file /Users/Documents/app-release/META-INF/CERT.RSA

查看自己签名文件里面的信息
keytool -list -v -keystore +自己的key路径

指定安装架构
adb install –abi armeabi-v7a /Users/jian/Desktop/tuofukmf-216-4.10.6-debug.apk
adb install –abi arm64-v8a

查看 Android 手机的 CPU 架构
adb shell
cat /proc/cpuinfo

提示[!] Android Studio (version 2021.2) ✗ Unable to find bundled Java version.
cd /Applications/Android\ Studio.app/Contents/jre
ln -s ../jre jdk
ln -s “/Library/Internet Plug-Ins/JavaAppletPlugin.plugin” jdk

查看 Android 手机的 CPU 架构

查看 Android 手机的 CPU 架构

查看 Android 手机的 CPU 架构
Win + R 然后输入 cmd
执行:

  1. adb shell
  2. cat /proc/cpuinfo

PD1938:/ $ cat /proc/cpuinfo
processor : 0
BogoMIPS : 52.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
CPU implementer : 0x41
CPU architecture: 8 (7 表示arm-v7,8表示arm-v8)
CPU variant : 0x1
CPU part : 0xd05
CPU revision : 0

processor : 1
BogoMIPS : 52.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x1
CPU part : 0xd05
CPU revision : 0

processor : 2
BogoMIPS : 52.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x1
CPU part : 0xd05
CPU revision : 0

易车一面面试题

易车一面面试题

易车一面:
1、Arouter原理
2、目前的组件化项目架构应用分层
3、业务模块直接的通信怎么做的,是在common里封装接口吗
4、组件化过程中遇到的困难,怎么解决的
5、不想在common里封装接口,想达到通信的目的,怎么做(自己设计路由框架怎么做)
6、集成启动的时候,各个业务模块的初始化启动怎么做(反射获取)
7、MVVM优点在哪
8、业务层怎么做管理,四个业务层都各自迭代,怎么协同管理(maven,aar)
9、apk包体积优化怎么做的
10、自己做热修复的系统怎么设计、插件什么格式下载下来
11、布局优化,内存优化怎么做的
12、约束布局
13、jvm内存划分,内存泄漏怎么发生的,垃圾回收,GcRoot都有哪些

数据结构基础知识

数据结构基础知识

跳表查询的时间复杂度分析

n/2、n/4、n/8、第k级索引节点的个数就是n/(2^k)

假设索引有h级,最高级的索引有2个节点。n/(2^h) = 2,从而求得h = log2(n) - 1

跳表:

原始链表大小为n,每2个结点抽1个,每层索引的节点数: n/2,n/4,n/8,…,8,4,2
原始链表大小为n,每3个结点抽1个,每层索引的节点数: n/3,n/9,n/27,…,9,3,1
空间复杂度是O(n)

跳表查询的时间复杂度分析
第k级索引
第k - 1 级索引

索引的高度:logn,每层索引遍历的节点个数:3
在跳表中查询任意数据的时间复杂度就是O(logn)

解决问题
升级维度
空间换时间

LRU最近最少使用
基于多链表来实现的。

可以通过HashMap + 双向链表实现。
HashMap保证通过key访问数据的时间为O(1),
双向链表则按照访问时间的顺序一次穿过每个数据。
之所以选择双向链表而不是单链表,是为了可以从中间任意节点修改链表结构,而不必从头结点开始遍历。

算法思考题

算法思考题

1.二叉树遍历 前序、中序、后序 时间复杂度是多少?
O(n),树的每个节点 有且仅访问一次。n为树的节点总数。

2.图的遍历时间复杂度是多少?
O(n),n为图里面的节点总数。

3.搜索算法DFS、BFS时间复杂度是多少?
O(n) n指的是搜索空间里面的节点总数。

4.二分查找 时间复杂度是多少?
O(logn)

oppo的面试题

oppo的面试题

collection和collections的区别
map遍历过程中删除数据会发生什么如何解决
1,Android为什么使用Dalvik 不用JVM Dalvik和ART的演变
2.双重锁单例 volitile关键字,sync锁
3.binder通信流程,跨进成通信方式,binder的大小
4.代理模式的实现
5.热修复原理 (双亲委托)。

oppo的面试题
1.tcp怎么保证数据传输的可靠性
2.多进程的好处和缺点
3.Service和Thread的区别
4.Socket有什么优化点
5.偏向锁的实现原理
6.CAS的实现原理
7.设计模式的设计原则
8.jvm的多线程机制
9.rsa加密原理
10.hashmap和treemap有什么区别
HashMap:基于哈希表实现 .优化HashMap空间的使用,可以调优初始容量和负载因子。适用于在Map中插入、删除和定位元素。
TreeMap:基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。适用于按自然顺序或自定义顺序遍历键(key)。

1.为什么ThreadLocalMap使用弱引用存储ThreadLocal?

假如使用强引用,当ThreadLocal不再使用需要回收时,发现某个线程中ThreadLocalMap存在该ThreadLocal的强引用,无法回收,造成内存泄漏。

因此,使用弱引用可以防止长期存在的线程(通常使用了线程池)导致ThreadLocal无法回收造成内存泄漏。

2.那通常说的ThreadLocal内存泄漏是如何引起的呢?

我们注意到Entry对象中,虽然Key(ThreadLocal)是通过弱引用引入的,但是value即变量值本身是通过强引用引入。

这就导致,假如不作任何处理,由于ThreadLocalMap和线程的生命周期是一致的,当线程资源长期不释放,即使ThreadLocal本身由于弱引用机制已经回收掉了,但value还是驻留在线程的ThreadLocalMap的Entry中。即存在key为null,但value却有值的无效Entry。导致内存泄漏。

ANR导致原因?

  1. cpu过载导致,全量logcat日志里会有相关的打印,各个进程cpu占用情况,这种一般不需要分析trace文件
  2. 频繁gc导致,全量日志anr之前会有频繁的gc打印,trace文件头部也会统计gc单次耗时,总次数和总耗时
    主线程也会进入wait状态,之后就是一系列的gc相关的线程 wait
  3. 死锁,这种我遇到的很少,就讲了下一般会打印资源is heldby xxx进程会形成互相持有的状态
13道数据结构和算法题总结

13道数据结构和算法题总结

Q1:什么是 AVL 树?
AVL 树 是平衡二叉查找树,增加和删除节点后通过树形旋转重新达到平衡。右旋是以某个节点为中心,将它沉入当前右子节点的位置,而让当前的左子节点作为新树的根节点,也称为顺时针旋转。同理左旋是以某个节点为中心,将它沉入当前左子节点的位置,而让当前的右子节点作为新树的根节点,也称为逆时针旋转。

Q2:什么是红黑树?
红黑树 是 1972 年发明的,称为对称二叉 B 树,1978 年正式命名红黑树。主要特征是在每个节点上增加一个属性表示节点颜色,可以红色或黑色。红黑树和 AVL 树 类似,都是在进行插入和删除时通过旋转保持自身平衡,从而获得较高的查找性能。与 AVL 树 相比,红黑树不追求所有递归子树的高度差不超过 1,保证从根节点到叶尾的最长路径不超过最短路径的 2 倍,所以最差时间复杂度是 O(logn)。红黑树通过重新着色和左右旋转,更加高效地完成了插入和删除之后的自平衡调整。

红黑树在本质上还是二叉查找树,它额外引入了 5 个约束条件:① 节点只能是红色或黑色。② 根节点必须是黑色。③ 所有 NIL 节点都是黑色的。④ 一条路径上不能出现相邻的两个红色节点。⑤ 在任何递归子树中,根节点到叶子节点的所有路径上包含相同数目的黑色节点。

这五个约束条件保证了红黑树的新增、删除、查找的最坏时间复杂度均为 O(logn)。如果一个树的左子节点或右子节点不存在,则均认定为黑色。红黑树的任何旋转在 3 次之内均可完成。

Q3:AVL 树和红黑树的区别?
红黑树的平衡性不如 AVL 树,它维持的只是一种大致的平衡,不严格保证左右子树的高度差不超过 1。这导致节点数相同的情况下,红黑树的高度可能更高,也就是说平均查找次数会高于相同情况的 AVL 树。

在插入时,红黑树和 AVL 树都能在至多两次旋转内恢复平衡,在删除时由于红黑树只追求大致平衡,因此红黑树至多三次旋转可以恢复平衡,而 AVL 树最多需要 O(logn) 次。AVL 树在插入和删除时,将向上回溯确定是否需要旋转,这个回溯的时间成本最差为 O(logn),而红黑树每次向上回溯的步长为 2,回溯成本低。因此面对频繁地插入与删除红黑树更加合适。

Q4:B 树和B+ 树的区别?
B 树中每个节点同时存储 key 和 data,而 B+ 树中只有叶子节点才存储 data,非叶子节点只存储 key。InnoDB 对 B+ 树进行了优化,在每个叶子节点上增加了一个指向相邻叶子节点的链表指针,形成了带有顺序指针的 B+ 树,提高区间访问的性能。

B+ 树的优点在于:

① 由于 B+ 树在非叶子节点上不含数据信息,因此在内存页中能够存放更多的 key,数据存放得更加紧密,具有更好的空间利用率,访问叶子节点上关联的数据也具有更好的缓存命中率。

② B+树的叶子结点都是相连的,因此对整棵树的遍历只需要一次线性遍历叶子节点即可。而 B 树则需要进行每一层的递归遍历,相邻的元素可能在内存中不相邻,所以缓存命中性没有 B+树好。但是 B 树也有优点,由于每个节点都包含 key 和 value,因此经常访问的元素可能离根节点更近,访问也更迅速。

Q5:排序有哪些分类?
排序可以分为内部排序和外部排序,在内存中进行的称为内部排序,当数据量很大时无法全部拷贝到内存需要使用外存,称为外部排序。

内部排序包括比较排序和非比较排序,比较排序包括插入/选择/交换/归并排序,非比较排序包括计数/基数/桶排序。

插入排序包括直接插入/希尔排序,选择排序包括直接选择/堆排序,交换排序包括冒泡/快速排序。

Q6:直接插入排序的原理?
稳定,平均/最差时间复杂度 O(n²),元素基本有序时最好时间复杂度 O(n),空间复杂度 O(1)。

每一趟将一个待排序记录按其关键字的大小插入到已排好序的一组记录的适当位置上,直到所有待排序记录全部插入为止。

Android 事件分发流程

Android 事件分发流程

前面一篇文章中我们分析了App返回按键的分发流程,从Native层到ViewRootImpl层到DocorView层到Activity层,以及在Activity中的dispatchKeyEvent方法中分发事件,最终调用了Activity的finish方法,即销毁Activity,所以一般情况下假如我们不重写Activity的onBackPress方法或者是onKeyDown方法,当我们按下并抬起返回按键的时候默认都是销毁当前Activity。而本文中我们主要介绍触摸事件的分发流程,从Native层到Activity层触摸事件的分发了流程和按键的分发事件都是类似的,这里我们可以根据异常堆栈信息看一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
at com.example.aaron.helloworld.MainActivity.dispatchTouchEvent(MainActivity.java:103)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2359)
at android.view.View.dispatchPointerEvent(View.java:8698)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4530)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4388)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3924)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3977)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3943)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4053)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3951)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4110)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3924)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3977)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3943)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3951)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3924)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6345)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6301)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6254)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6507)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)

这样经过一系列的方法调用之后最终调用了Activity的dispatchTouchEvent方法,而我们也是从Activiyt的dispatchTouchEvent方法开始对触摸事件的分发进行分析。

在具体查看Activity的dispatchTouchEvent方法之前我们先简单介绍一下触摸事件,触摸事件是由一个触摸按下事件、N个触摸滑动事件和一个触摸抬起事件组成的,通常的一个触摸事件中只能存在一个触摸按下和一个触摸抬起事件,但是触摸滑动事件可以有零个或者多个。好了,知道这个概念以后,下面我们就具体看一下Activity中的dispatchTouchEvent的实现逻辑。

1
2
3
4
5
6
7
8
9
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
Android 基础知识总结

Android 基础知识总结

Activity生命周期

img

Fragment生命周期

img

Activity****四种启动模式

  • standard : 标准模式,每次启动Activity都会创建一个新的Activity实例,并且将其压入任务栈栈顶,而不管这个Activity是否已经存在。Activity的启动三回调(onCreate()->onStart()->onResume())都会执行。

  • singleTop : 栈顶复用模式.这种模式下,如果新Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建,所以它的启动三回调就不会执行,同时Activity的onNewIntent()方法会被回调.如果Activity已经存在但是不在栈顶,那么作用与standard**模式一样.

  • singleTask: 栈内复用模式.创建这样的Activity的时候,系统会先确认它所需任务栈已经创建,否则先创建任务栈.然后放入Activity,如果栈中已经有一个Activity实例,那么这个Activity就会被调到栈顶,onNewIntent(),并且singleTask会清理在当前Activity上面的所有Activity.(clear top)

  • singleInstance : 加强版的singleTask模式,这种模式的Activity只能单独位于一个任务栈内,由于栈内复用的特性,后续请求均不会创建新的Activity,除非这个独特的任务栈被系统销毁了

百度二面面试题

百度二面面试题

  1. 正向代理,反向代理
    正向代理 client proxy -> service client -> proxy service
  2. 数据库 后10条数据 sql语句怎么写
    Select * from user order by id desc limit 10
  3. 非关系型数据库库和关系型数据库区别
    关系型数据天然就是表格式的,因此存储在数据表的行和列中。数据表可以彼此关联协作存储,也很容易提取数据。
    非关系型数据不适合存储在数据表的行和列中,而是大块组合在一起。非关系型数据通常存储在数据集中,就像文档、
    键值对或者图结构。你的数据及其特性是选择数据存储和提取方式的首要影响因素。
  4. 多个数据库版本升级 如何设计减少后期开发人员工作量
  5. 计算2进制数据有多少个1
  6. java文件编译过程
    通过javac 将 java文件编译成.class字节码文件
  7. dex文件如何加载
    DexClassLoader PathClassLoader 。DexClassLoader 加载外部文件。PathClassLoader加载内部应用。继承自BaseDexClassLoader,内部包含DexElement 数组。
  8. 列表卡顿优化
  9. 内存紧张是否会导致卡顿
  10. synchronized作用, 如何 让多个实例的同一个方法只有一个线程访问
  11. 计算二叉树深度
  12. 打印斐波那契数列
    0,1,1,2,3,5,8,13,21,34,55,89,144
  13. 微信朋友圈 图片点击放大效果和手指拖动效果如何实现
  14. anr问题怎么分析
  15. dalvik 虚拟机和ART虚拟机主要区别
  16. socket是什么
  17. tcp协议的上层协议有哪些
    http websocket mqtt

:D 一言句子获取中...