Skip to content

Commit

Permalink
Update 面试笔记.md
Browse files Browse the repository at this point in the history
  • Loading branch information
WithLei committed May 4, 2019
1 parent 153d8a9 commit 8441157
Showing 1 changed file with 81 additions and 8 deletions.
89 changes: 81 additions & 8 deletions MyPart/面试笔记.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
@[toc]
# Android相关
## AMS相关
ActivityManagerService是Android中最核心的服务 , 主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,其职责与操作系统中的进程管理和调度模块类似。
看源码谈谈AMS启动过程:[ActivityManagerService分析——AMS启动流程](https://blog.csdn.net/dutedehuai/article/details/53495185)

## Activity相关
### SingleTask优化
```java
Expand Down Expand Up @@ -92,6 +96,11 @@ START_STICKY,START_NOT_STICKY,START_REDELIVER_INTENT

[service详细介绍](https://blog.csdn.net/hdhhd/article/details/80612726)

## Service 如何和 Activity 进行通信?
① 通过绑定服务的方式。在绑定的服务中声明一个Binder类,并创建一个Binder对象,在onBind()函数中返回这个对象,并让Activity实现ServiceConnection接口,在OnServiceConnected方法中获取到Service提供的这个Binder对象,通过这个对象的各种自定义的方法就能完成Service与Activity的通信。
② 通过Intent的方式,在StartService()中需要传入一个Intent对象作为参数,通过这个Intent实例对象进行实现通信。
③ 通过Callback和Handler的方式,在绑定的服务中声明一个Binder类,并创建一个Binder对象,在onBind()函数中返回这个对象,让Activity实现ServiceConnection接口,并且在OnserviceConnected方法中实例化Service中的CallBack接口,并且实现OnDataChange()方法,其中的实质是一段Handler代码,可以在其中完成耗时操作,以这种方式完成通信。

## BroadcastReciever相关
写一个类继承BroadcastReceiver重写onReceive方法,注意onReceive是主线程不要做耗时操作否则阻塞10s会ANR,onReceive()中耗时操作不能开线程做,可以使用goAsync()或使用service来做(由于onReceive在结束后会释放资源,依赖线程也很有可能会被释放)

Expand Down Expand Up @@ -191,7 +200,7 @@ ANR(Application Not responding)。Android中,主线程(UI线程)如果在规
(4) ContentProvider的publish在10s内没进行完

## 内存泄露的场景有哪些?内存泄漏分析工具使用方法?
常见的内存泄露有:
常见的内存泄露有:
1.非静态内部类的静态实例
非静态内部类会持有外部类的引用,如果非静态内部类的实例是静态的,就会长期的维持着外部类的引用,组织被系统回收,解决办法是使用静态内部类

Expand Down Expand Up @@ -224,14 +233,14 @@ bitmap是比较占内存的,所以一定要在不使用的时候及时进行

而对于内存泄露的检测,常用的工具有LeakCanary、MAT(Memory Analyer Tools)、Android Studio自带的Profiler。

## 如何避免OOM?
## 如何避免OOM?
1.使用更加轻量的数据结构:如使用ArrayMap/SparseArray替代HashMap,HashMap更耗内存,因为它需要额外的实例对象来记录Mapping操作,SparseArray更加高效,因为它避免了Key Value的自动装箱,和装箱后的解箱操作

2.便面枚举的使用,可以用静态常量或者注解@IntDef替代
2.避免枚举的使用,可以用静态常量或者注解@IntDef替代

3.Bitmap优化:
a.尺寸压缩:通过InSampleSize设置合适的缩放
b.颜色质量:设置合适的format,ARGB_6666/RBG_545/ARGB_4444/ALPHA_6,存在很大差异
3.Bitmap优化:
a.尺寸压缩:通过InSampleSize设置合适的缩放
b.颜色质量:设置合适的format,ARGB_6666/RBG_545/ARGB_4444/ALPHA_6,存在很大差异
c.inBitmap:使用inBitmap属性可以告知Bitmap解码器去尝试使用已经存在的内存区域,新解码的Bitmap会尝试去使用之前那张Bitmap在Heap中所占据的pixel data内存区域,而不是去问内存重新申请一块区域来存放Bitmap。利用这种特性,即使是上千张的图片,也只会仅仅只需要占用屏幕所能够显示的图片数量的内存大小,但复用存在一些限制,具体体现在:在Android 4.4之前只能重用相同大小的Bitmap的内存,而Android 4.4及以后版本则只要后来的Bitmap比之前的小即可。使用inBitmap参数前,每创建一个Bitmap对象都会分配一块内存供其使用,而使用了inBitmap参数后,多个Bitmap可以复用一块内存,这样可以提高性能

4.StringBuilder替代String: 在有些时候,代码中会需要使用到大量的字符串拼接的操作,这种时候有必要考虑使用StringBuilder来替代频繁的“+”
Expand Down Expand Up @@ -314,13 +323,72 @@ ALTER TABLE table_name DROP COLUMN column_name
## AsyncTask、HandlerThread、IntentService区别和使用
AsyncTask,HandlerThread,IntentService

- AsyncTask原理:内部是Handler和两个线程池实现的,Handler用于将线程切换到主线程,两个线程池一个用于任务的排队,一个用于执行任务,当AsyncTask执行execute方法时会封装出一个FutureTask对象,将这个对象加入队列中,如果此时没有正在执行的任务,就执行它,执行完成之后继续执行队列中下一个任务,执行完成通过Handler将事件发送到主线程。AsyncTask必须在主线程初始化,因为内部的Handler是一个静态对象,在AsyncTask类加载的时候他就已经被初始化了。在Android3.0开始,execute方法串行执行任务的,一个一个来,3.0之前是并行执行的。如果要在3.0上执行并行任务,可以调用executeOnExecutor方法
- AsyncTask原理:内部是Handler和两个线程池实现的,Handler用于将线程切换到主线程,两个线程池一个用于任务的排队,一个用于执行任务,当AsyncTask执行execute方法时会封装出一个FutureTask对象,将这个对象加入队列中,如果此时没有正在执行的任务,就执行它,执行完成之后继续执行队列中下一个任务,执行完成通过Handler将事件发送到主线程。AsyncTask必须在主线程初始化,因为内部的Handler是一个静态对象,在AsyncTask类加载的时候他就已经被初始化了。在Android3.0开始,execute方法串行执行任务的,一个一个来,3.0之前是并行执行的。如果要在3.0上执行并行任务,可以调用executeOnExecutor方法

- HandlerThread原理:继承自 Thread,start开启线程后,会在其run方法中会通过Looper 创建消息队列并开启消息循环,这个消息队列运行在子线程中,所以可以将HandlerThread 中的 Looper 实例传递给一个 Handler,从而保证这个 Handler 的 handleMessage 方法运行在子线程中,Android 中使用 HandlerThread的一个场景就是 IntentService

- IntentService原理:继承自Service,它的内部封装了 HandlerThread 和Handler,可以执行耗时任务,同时因为它是一个服务,优先级比普通线程高很多,所以更适合执行一些高优先级的后台任务,HandlerThread底层通过Looper消息队列实现的,所以它是顺序的执行每一个任务。可以通过Intent的方式开启IntentService,IntentService通过handler将每一个intent加入HandlerThread子线程中的消息队列,通过looper按顺序一个个的取出并执行,执行完成后自动结束自己,不需要开发者手动关闭
[IntentService分析](https://www.imooc.com/article/40482)

## Bitmap优化
主动释放Bitmap资源
```java
bitmap.recycle();
bitmap = null;
```

在不加载图片的前提下获得图片的宽高
```java
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
```

图片大小压缩,采样率一般是2的指数,即1、2、4、8、16……
```java
bitmapFactoryOptions.inSampleSize = 2;
```

图片像素压缩
Android中图片有四种属性,分别是:
ALPHA_8:每个像素占用1byte内存
ARGB_4444:每个像素占用2byte内存
ARGB_8888:每个像素占用4byte内存 (默认)
RGB_565:每个像素占用2byte内存
Android默认的颜色模式为ARGB_8888,这个颜色模式色彩最细腻,显示质量最高。但同样的,占用的内存也最大。 所以在对图片效果不是特别高的情况下使用RGB_565(565没有透明度属性),如下:
```java
public static Bitmap readBitMap(Context context, intresId) {
BitmapFactory.Options opt = newBitmapFactory.Options();
opt.inPreferredConfig = Bitmap.Config.RGB_565;
opt.inPurgeable = true;
opt.inInputShareable = true;
//获取资源图片
InputStreamis = context.getResources().openRawResource(resId);
returnBitmapFactory.decodeStream(is, null, opt);
}
```

# Android框架相关
## LeakCanary相关
关键词:activity监听 weakreference referenceQueue
1.activity被移除
2.
[相关播客](https://www.jianshu.com/p/261e70f3083f)

## Retrofit相关
[相关博客](https://www.jianshu.com/p/89ce9bf53073)

## RxJava相关

## okHttp相关

## rxjava相关

## mvp相关


# Java相关
该部分内容笔者按照该博客集合顺序+阅读源码进行复习。
[Java相关博客集合](https://www.cnblogs.com/skywang12345/category/455711.html)
## collection里面有什么子类?
(其实面试的时候听到这个问题的时候,你要知道,面试官是想考察List,Set)
list和set是实现了collection接口的。
Expand All @@ -343,6 +411,10 @@ list和set是实现了collection接口的。
- 如果你想保证插入元素的唯一性,也就是你不想有重复值的出现,那么可以选择一个 Set 的实现类,比如 HashSet、LinkedHashSet 或者 TreeSet。所有 Set 的实现类都遵循了统一约束比如唯一性,而且还提供了额外的特性比如 TreeSet 还是一个 SortedSet,所有存储于 TreeSet 中的元素可以使用 Java 里的 Comparator 或者 Comparable 进行排序。LinkedHashSet 也按照元素的插入顺序对它们进行存储。
- 如果你以键和值的形式进行数据存储那么 Map 是你正确的选择。你可以根据你的后续需要从 Hashtable、HashMap、TreeMap 中进行选择。

## fail-fast机制
“快速失败”也就是fail-fast,它是Java集合的一种错误检测机制。当多个线程对集合进行结构上的改变的操作时,有可能会产生fail-fast机制。记住是有可能,而不是一定。例如:假设存在两个线程(线程1、线程2),线程1通过Iterator在遍历集合A中的元素,在某个时候线程2修改了集合A的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么这个时候程序就会抛出ConcurrentModificationException 异常,从而产生fail-fast机制。
[相关博客](https://www.cnblogs.com/chenssy/p/3870107.html)

## ArrayList和LinkedList的区别
- Arraylist
底层是基于动态数组,根据下表随机访问数组元素的效率高,向数组尾部添加元素的效率高;但是,删除数组中的数据以及向数组中间添加数据效率低,因为需要移动数组。例如最坏的情况是删除第一个数组元素,则需要将第2至第n个数组元素各向前移动一位。而之所以称为动态数组,是因为Arraylist在数组元素超过其容量大,Arraylist可以进行扩容(针对JDK1.8? 数组扩容后的容量是扩容前的1.5倍)
Expand All @@ -362,7 +434,8 @@ list和set是实现了collection接口的。
- 扩容针对整个Map,每次扩容时,原来数组中的元素依次重新计算存放位置,并重新插入
- 插入元素后才判断该不该扩容,有可能无效扩容(插入后如果扩容,如果没有再次插入,就会产生无效扩容)
- 当Map中元素总数超过Entry数组的75%,触发扩容操作,为了减少链表长度,元素分配更均匀
- 计算index方法:index = hash & (tab.length – 1)
- 计算index方法:index = hash & (tab.length – 1)
[HashMap面试题](https://baijiahao.baidu.com/s?id=1618550070727689060&wfr=spider&for=pc)

### ConcurrentHashMap
- 底层采用分段的数组+链表实现,线程安全
Expand Down

0 comments on commit 8441157

Please sign in to comment.