面试题系列

jsonChao大佬系列面试题
公众号面试题
jsonChao腾讯面试题
一天一道Android面试题
「码个蛋」每日一题
剑指offer
RecyclerView如何优化
https://www.jianshu.com/p/afd0a19533af

1、java虚拟机组成、回收机制、hashMap1.8之前与1.8的区别
hashMap1.8之前是数组+链表 1.8开始是数组+链表+红黑树
2、链表和红黑树的算法复杂度
3、RxJava线程切换机制、okhttp底层原理、retrofit底层原理
4、手写冒泡排序、双重锁单例
5、反射的原理 ,如何自定义注解
https://blog.csdn.net/ju_362204801/article/details/90578678

6、用过第三方的sdk,比如友盟,它底层是如何监测统计的
7、应用崩溃会回调那个函数
8、安卓为什么只能在主线程更新UI
9、LeckCanary这个库,是如何进行内存检测的?
10、Handler的postDelay是如何实现delay的?handler是如何保证消息不混乱?
11、RxJava的map和flatMap作用,call方法是干嘛的?
12、Recyclerview嵌套Recyclerview,里面的Recyclerview复用会失效,如何设计才能是其复用生效?
今天面试

1、实现一个String转int方法

Integer.valueOf(str).intValue();
int a = Integer.parseInt(str);

2、HashCode
HashMap (http://www.cnblogs.com/tonyluis/p/5671873.html)

hashCode()是一个native方法,意味着方法的实现和硬件平台有关,默认实现和虚拟机有关,
对于有些JVM,hashCode()返回的就是对象的地址,大多时候JVM根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,
并返回。

在Java中,hashCode()方法的主要作用是为了配合基于散列的集合(HashSet、HashMap)一起正常运行。
当向集合中插入对象时,调用equals()逐个进行比较,这个方法可行却效率低下。因此,先比较hashCode再调用equals()会快很多。

3、String StringBuffer StringBuilder
4、冒泡 快排 算法 时间复杂度
equals == (s1 ="hello" , s2 = "hello", s1.equals(s2); true?false 引出了 equals里的 == )

5、TCP/IP 三次握手(SYN ACK) 四次挥手 :
一个 主线程 假如有2个handler 有几个Looper 几个MQ msg Looper里循环是while 还是for
子线程 能否创建handler (可以,Looper.prepare(); Handler... Looper.loop(); )

可以看到Looper把消息分发给handler, handler最终拿到消息调用handleMessage(msg),
此时我们在前台调用的时候重写的handleMessage(msg)拿到的这个msg就是我们需要处理的Message.
这样就完成了handler1把消息传递,然后把这个消息打上这个handler1的标记,
最后looper再拿到打上这个handler1标记的消息,再分发给handler1,此时handler1拿到的就是它上次发送的那个消息.

Intent 里的 action catagory (隐式传递中 action 可以没有或者多个 catagory只能有一个 默认default)
显示传递:明确的指明对应的activity。 隐士传递:不指名具体的activity,而是通过data action等去筛选。

Activity A --->B 之间生命周期
Activity A ---> B(透明主题) 之间生命周期
service 能否进行耗时操作 是否于调用它的Ac 同生命周期....

什么是过度绘制 如何避免?
解:就是一个界面绘制很多次,
1 尽量多使用RelativeLayout和LinearLayout, 不要使用绝对布局AbsoluteLayout,
2 将可复用的组件抽取出来并通过include标签使用;
3 使用merge标签减少布局的嵌套层次
4 merge

View的绘制过程:
measure layout draw

 /**
   * 不用java内置函数,将String字符串转换为数字
   * @param s
   * @return
   * @throws Exception
   */
  public static int atoi(String s) throws Exception{
    int retInt = 0;
    if (s == null || s.length() == 0) {
      throw new Exception("要转换的字符串为空,无法转换!");
    }
    boolean isNegative = false;
    for (int i = 0; i < s.length(); i++) {
      if (i==0) {
        if(s.charAt(i)=='-'){
          isNegative = true;
          continue;
        }
      }else{
        if(s.charAt(i)>'9' || s.charAt(i)<'0'){
          throw new Exception("要转换的字符串格式错误,无法转换!");
        }
      }
      retInt *=10;
      retInt += s.charAt(i) - '0';
    }
    return isNegative ? -retInt : retInt;
  }

String StringBuffer StringBuilder
1.可变与不可变

String类中使用字符数组保存字符串,因为有“final”修饰符,string对象是不可变的。private final char value[];
  StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,这两种对象都是可变的。char[] value;

2.是否多线程安全
  String中的对象是不可变的,也就可以理解为常量,显然线程安全。
  StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。
  StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。

3.StringBuilder与StringBuffer共同点

StringBuilder与StringBuffer有公共父类AbstractStringBuilder(抽象类)。
  抽象类与接口的其中一个区别是:抽象类中可以定义一些子类的公共方法,子类只需要增加新的功能,不需要重复写已经存在的方法;而接口中只是对方法的申明和常量的定义。
  StringBuilder、StringBuffer的方法都会调用AbstractStringBuilder中的公共方法,如super.append(...)。只是StringBuffer会在方法上加synchronized关键字,进行同步。
  最后,如果程序不是多线程的,那么使用StringBuilder效率高于StringBuffer。

冒泡 快排 算法 时间复杂度(http://blog.csdn.net/lsh_2013/article/details/47280135)

TCP/IP 三次握手(SYN ACK) 四次挥手
标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义如下:
URG:紧急指针(urgent pointer)有效。
ACK:确认序号有效。
PSH:接收方应该尽快将这个报文交给应用层。
RST:重置连接。
SYN:发起一个新连接。
FIN:释放一个连接。

TCP三次握手 
    第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。 
    第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,
                并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。 
    第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,
                Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,
                完成三次握手,随后Client与Server之间可以开始传输数据了。

TCP四次挥手 
    第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。 
    第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。 
    第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。 
    第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。 

为什么建立连接是三次握手,而关闭连接却是四次挥手呢? 
    这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
    而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,
    也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。

插入排序 通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

冒泡排序 重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。

快速排序 通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

名称 时间复杂度
插入排序 平均O(n^2) 最优O(n) 最差O(n^2)

冒泡排序 平均O(n^2) 最优O(n) 最差O(n^2)

冒泡排序 平均O(nlogn) 最优O(nlogn) 最差O(n^2)

java中内存主要包含4块,即heap(堆内存)、stack(栈内存)、data segment(静态变量或是常量存放区)、codesegment(方法区).
堆内存中存放的是new出的对象,new出的对象只包含成员变量。
栈内存中:存放的是局部成员变量。对于基本的数据类型存放的是基本变量的值,而对于对象变量,存放的是堆内存的地址。
静态、常量区:存放的是静态变量(类变量)或是常量。
方法区:存放的是对象的方法。因此即使new出多个对象也是只是存在一个方法。

垃圾回收机制:

回收机制,分代回收:

年轻代:1 Eden 区 和2个Survivor 区
年老代
永久代
分代回收分为了三个代,每个代的垃圾回收时机和频率是不一样的,因此才用的回收算法也不一样。
总的来说:年轻代的回收频率很高,对象的生命周期比较短暂,当经过一定次数的回收周期之后,年轻代的对象还存活的话,就会被移动到年老代,年老代的回收比较耗时,回收频率较低,回收成本较大。


1、Java1.7新特性:
①运用List tempList = new ArrayList<>();即泛型实例化类型自动推断
②switch中可以使用字符串了
jdk1.8新特性:
Lambda表达式。
2、map集合的遍历,如何对map进行排序?
HashMap:我们最常用的Map,它根据key的HashCode 值来存储数据,根据key可以直接获取它的Value,
同时它具有很快的访问速度。HashMap最多只允许一条记录的key值为Null(多条会覆盖);允许多条记录的Value为 Null。非同步的。
HashMap的值是没有顺序的,他是按照key的HashCode来实现的。

TreeMap: 能够把它保存的记录根据key排序,默认是按升序排序,也可以指定排序的比较器,
     当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。

Hashtable: 与 HashMap类似,不同的是:key和value的值均不允许为null;它支持线程的同步,
      即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。

3 list集合的遍历和排序??
collections.sort();

4。排序算法都有哪些?哪个的时间复杂度最低?

5 json的数据类型都有哪些?
布尔 对象 数组 字符串,整型

6.网络请求的缓存怎么实现?
Cache cache = new Cache();

7.项目中哪些功能是你做的?比较亮眼的功能。

8 数据库框架用到哪些??sqlite的一些问题?

9.用到了哪些动画??
帧动画和补间动画

10.APP性能优化。。
电量 网络快慢 app响应速度 app包的大小。

    网络优化:加入一些缓存。

11.如何对播放的视频实现加密?

12、屏幕适配:
接下来介绍一种方法:百分比适配方法,步骤如下:
1. 以某一分辨率为基准,生成所有分辨率对应像素数列表
2. 将生成像素数列表存放在res目录下对应的values文件下
3. 根据UI设计师给出设计图上的尺寸,找到对应像素数的单位,然后设置给控件即可

13、EventBus是如何实现的?

14、Glide和Picasso的区别?Glide如何加载圆角图片?如何监听加载的过程?
1.Glide的一个明显的优点就是它可以加载gif图片。
2. 就是说你可以传递 Activity 或者 Fragment 的 context 给 Glide.with(),
然后 Glide 就会非常智能的同 Activity 的生命周期集成, 比如 OnResume 或者 onPause():
3.Gilde比Picasso大一些。

15、handler的机制,handler为什么会出现内存泄漏?怎么解决?
handler负责发送消息,Looper负责接受Handler发送的消息,并直接把消息回传给自己。
Message人Queue负责存储消息。
内存泄漏:1.handler,messageQueue 和message都是相互关联在一起的,如何handler发送完消息,handler的生命周期和activity
是不一致的。比如

如果在任务未执行完时,Activity被关闭了,Activity已不再使用,此时由GC来回收掉Activity对象。
由于子线程未执行完毕,子线程持有Handler的引用,
而Handler又持有Activity的引用,这样直接导致Activity对象无法被GC回收,即出现内存泄漏。


解决方式:1.将Handler声明为静态内部类。因为静态内部类不会持有外部类的引用,所以不会导致外部类实例出现内存泄露。
          2.在Handler中添加对外部Activity的弱引用。由于Handler被声明为静态内部类,不再持有外部类对象的引用,
 导致无法在handleMessage()中操作Activity中的对象,所以需要在Handler中增加一个对Activity的弱引用。

16、View的绘制流程:

17、时间分发流程View和ViewGroup?

事件产生后,因为ViewGroup在外层,所以ViewGroup先接受到这个事件对象event,
并且将这个event对象传递给它(ViewGroup)本身的dispatchTouchEvent方法。在dispatchTouchEvent中会调用onInterceptTouchEvent方法, 
如果onInterceptTouchEvent返回true,那么说明这次触摸事件,ViewGroup本身要响应,也就是拦截该事件,调用自己的onTouchEvent方法,
不再向下(子视图)传递。
如果onInterceptTouchEvent返回false,那么说明这次触摸事件,ViewGroup不响应,不拦截,
会将该事件event传递到子视图中(向下传递),接着子视图的dispatchTouchEvent就会被调用,直到事件被最终处理,整个分发过程才结束。
如果View没有对Action_Down进行消费,之后的事件就不会传递过来,也就是说Action_down必须返回为true,之后的事件才会传递过来。

18、三级缓存:

19.synchronized()的同步,结合单例模式进行解释。。

20.观察者模式的例子。
关注微信公众号。

21.内存泄漏和内存溢出:
内存泄漏:就是一个对象已经不需要再使用,但是其他对象仍然持有这个对象的引用,导致它的内存
不能回收,这就是内存泄漏。
内存溢出:内存泄漏慢慢累积,导致内存溢出。

内存泄漏的导致:
1.资源对象未关闭:比如File,cursor。
2.没有使用ConVertView.
3.bitmap没有回收。
4.集合中对象不用的时候没清理掉。

LeakCanary可以检测内存泄漏。

22.behavior:

23.anr:
手触摸5秒。brodeCast10秒。service20秒。

24.listView如何优化,滑动的时候不卡顿???

1.getView不要进行耗时操作
2.子条目不要进行过度的绘制。结构尽量要简单。
3.使用convertView进行复用子条目。

25.okhttp源码:
26.进程间如何进行通信?
其中Activity可以跨进程调用其他应用程序的Activity;
Content Provider可以跨进程访问其他应用程序中的数据(以Cursor对象形式返回),当然,也可以对其他应用程序的数据进行增、删、改操 作;
Broadcast可以向android系统中所有应用程序发送广播,而需要跨进程通讯的应用程序可以监听这些广播;Service和Content Provider类似,也可以访问其他应用程序中的数据,但不同的是,
Content Provider返回的是Cursor对象,
而Service返回的是Java对象,这种可以跨进程通讯的服务叫AIDL服务。

28.如何进行布局优化:
1.尽量减少嵌套
2.不要让View过度的绘制
3.使用include style merge

29.service可以弹出dialog吗?和activity弹出dialog有什么区别?
可以,如果需要在servcie中显示需要把dialog设置成一个系统的dialog,即全局 性质的提示框,
所以只要手机处于开机状态,无论它现在处于何种界面之下,
只要调用alter.show(),就会弹出提示框来。需要在show() 调用之前添加以下代码:
dialog.getWindow().setType((WindowManager.LayoutParams.TYPE_SYSTEM_ALERT));

30.链表如何实现?排序算法??

31.什么是过度的绘制:
1.布局设计在牵涉到嵌套时,应该注意嵌套的布局的背景色是否和被嵌套的布局背景色一致,如果一致可以考虑去除相同的背景色,减少绘制;
2.在布局中,如果存在多个线性布局重叠时,可以考虑只针对最上层的布局设置背景色,
而不需要每一个布局(例如LinearLayout)都设置背景色,过多的相同的背景色会导致过度绘制;
3.在设计到activity类中,如果牵涉到的布局存在背景色,可以考虑消除窗口的背景色,减少1X的绘制

32.tcp协议由几层组成?
TCP/IP通讯协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求。
这4层分别为: 第一层是应用层,应用程序间沟通的层。
第二层是传输层,在此层中, 它提供了节点间的数据传送服务,这一层负责传送数据,并且确定数据已被送达并接收。
第三层是互连网络层,负责提供基本的数据封包传送功能,让每一块数据包都能够到达目的主机(但不检查是否被正确接收)。
第四层是网络接口层,对实际的网络媒体的管理,定义如何使用实际网络来传送数据。

1.当对网络通讯质量有要求的时候,比如:整个数据要准确无误的传递给 
对方,这往往用于一些要求可靠的应用,比如HTTP、HTTPS、FTP等 

2.当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可 
以使用UDP。比如QQ语音,QQ视频。 

33.Android的启动模式:
standard:怎么样都要创建

singleTop:顶上不是target Activity,new一个

singleTask:顶上不是target Activity,移除target之上的,把自己变成top。

singleInstance:开辟私有的task,完全独立于程序的其他activity的task。

使用场景:

standard:普通activity

singleTop:要展示推送过来的消息

singleTask:程序入口等启动页面

singleInstance:完全独立的,类似闹钟的提示

34.属性动画:
1.ObjectAnimator,,单一动画类。
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "alpha", 1f, 0f, 1f);
animator.setDuration(2000);
animator.start();

ofFloat中的参数:
imageView:执行动画的View;
"alpha":表示透明动画;
1f:起始透明度;
0f:动画结束后的透明度;

    2.组合动画类:AnimatorSet:

AnimatorSet:这个类提供了一个play()方法,调用后将会返回一个AnimatorSet.Builder的实例,
AnimatorSet.Builder中包括以下四个方法:

after(Animator anim) :将现有动画插入到传入的动画之后执行

     after(long delay) :将现有动画延迟指定毫秒后执行

 before(Animator anim): 将现有动画插入到传入的动画之前执行 

with(Animator anim) :将现有动画和传入的动画同时执行

35.遍历Android外部存储,找出所有txt文件

     File path = Environment.getExternalStorageDirectory();// 获得SD卡路径
     // File path = new File("/mnt/sdcard/");
     File[] files = path.listFiles();// 读取
     getFileName(files);

  private void getFileName(File[] files) {
    if (files != null) {// 先判断目录是否为空,否则会报空指针
      for (File file : files) {
        if (file.isDirectory()) {
          Log.i("zeng", "若是文件目录。继续读1" + file.getName().toString() + file.getPath().toString());
          getFileName(file.listFiles());
          Log.i("zeng", "若是文件目录。继续读2" + file.getName().toString() + file.getPath().toString());
        } else {
          String fileName = file.getName();
          if (fileName.endsWith(".txt")) {
            HashMap map = new HashMap();
            String s = fileName.substring(0, fileName.lastIndexOf(".")).toString();
            Log.i("zeng", "文件名txt::  " + s);
            map.put("Name", fileName .substring(0, fileName.lastIndexOf(".")));
            name.add(map);
          }
        }
      }
    }
  }

2、Rxjava操作符 https://www.jianshu.com/p/cd984dd5aae8
3、retrofit的原理 https://www.jianshu.com/p/c1a3a881a144

4、屏幕适配:https://mp.weixin.qq.com/s/4uE-MNWzBShGw9OY-pTAKA
density = dpi / 160 ,dp = px / density
https://mp.weixin.qq.com/s/X-aL2vb4uEhqnLzU5wjc4Q

6、Android8.0的适配:
1、Android O将严格限制后台进程对手机资源的调用
2、 引入了通知渠道,其允许您为要显示的每种通知类型创建用户可自定义的渠道
3、可在不同设备型号上显示为各种不同的形状。
7、ontouchlisner和onTouchEvent???

8、能否创建两个子线程进行handler通信??
子线程可以创建Handler,用到HandlerThread和主线程进行通信。https://www.cnblogs.com/lang-yu/p/6228832.html

9、屏幕适配用到哪些?
10、final和static的区别?final怎么用?接口里面可以定义属性吗?
接口是不能创建对象的,所以必须用static,接口中的变量不能被修改,所以必须是final。

11、okhttp源码?okhttp如何进行封装?
12、webView和js的交互 https://www.jianshu.com/p/345f4d8a5cfa,java传一段json给他。
13、fragment和Fragment如何通信,fragment和activity如何通信?
```
final mFragment fragment = new mFragment();
// 步骤4:创建Bundle对象
// 作用:存储数据,并传递到Fragment中

  Bundle bundle = new Bundle();

    // 步骤5:往bundle中添加数据
 
  bundle.putString("message", "I love Google");

 // 步骤6:把数据设置到Fragment中
    fragment.setArguments(bundle);
  getArguments();
     
fragment向activity传值。用接口回调。
14、网页中如何打开一个APP  ,在清单文件中配置intent-filter
     
    
      
      
      

15、Android中如何画一个圆,实心圆和空心圆?
Collection:
  (1) List:     ArrayList   
        LinkedList
        Vector

        ArrayList 是一个可改变大小的数组.当更多的元素加入到ArrayList中时,其大小将会动态地增长.内部的元素可以直接通过get与set方法进行访问,因为ArrayList本质上就是一个数组.
        LinkedList 是一个双链表,在添加和删除元素时具有比ArrayList更好的性能.但在get与set方面弱于ArrayList.
        当然,这些对比都是指数据量很大或者操作很频繁的情况下的对比,如果数据和运算量很小,那么对比将失去意义.
        Vector 和ArrayList类似,但属于强同步类。如果你的程序本身是线程安全的(thread-safe,没有在多个线程之间共享同一个集合/对象),那么使用ArrayList是更好的选择。
        Vector和ArrayList在更多元素添加进来时会请求更大的空间。Vector每次请求其大小的双倍空间,而ArrayList每次对size增长50%.
        而 LinkedList 还实现了 Queue 接口,该接口比List提供了更多的方法,包括 offer(),peek(),poll()等.
  (2) Set
        HashSet:元素无序,元素允许为null
        TreeSet:元素按字符串顺序排序存储,元素不允许为null。
        HashSet是使用散列表进行存储,元素无序,元素允许为null。TreeSet是使用树结构来进行存储,元素按字符串顺序排序存储,元素不允许为null。
    Map:
    HashMap
    TreeMap
    HashTable
17、继承封装多态
18、APP是一个进程吗?
19、recyclerView的adapter有哪些的方法?
20、数组和集合的区别
21、webView的一些方法
22、Android中用到的设计模式。设计模式中用到的一些原则。
24、如何得到一个对象??反射?

25、泛型用在什么地方?
       封装的时候用到泛型
26、加密算法有哪些?md5,RES,
27、socket、udp的区别?
28、mvp设计模式??怎么写?mvp有啥好处
       视图逻辑和业务逻辑分别抽象到了View和Presenter的接口中去,提高代码的可阅读性。
       1、在一个类里面。定义两个接口,视图接口和逻辑接口。
       presenter类   实现presenter接口的方法。调用View接口的方法。
       activity类。实现视图的逻辑,调用逻辑接口的方法,实现View接口的方法。

29、如何上传多张图片??byte字节流??冷启动和热启动??内存泄漏??多线程下载APK。
     上传图片需要用到File,MultipartBody.builder.addFormDataPart

2019年6月10日22:30:10
1、如何保证多线程并发。sleep和wait
2、IntentService和Service的区别
3、Handler机制
4、自定义一个缩放控件什么思路
5、如何自定义一个垂直布局
6、rxjava的map和FlatMap
7、线程的创建方式,有什么区别
8、service的生命周期
9、权限的动态申请
10、http请求你了解多少?get和post请求,http如何进行加密的?
12、如何进行参数的加密
13、单例的特点
14、对称性加密和非对称加密。MD5加密的用法?
15、安卓虚拟机和java虚拟机的区别?
16、冒泡排序的时间复杂度
17、binder的原理。
18、Rxjava的调度操作符有哪些?
19、java多线程通信。
20、手写排序算法。

21、线程池有几种。
22、手写观察者。
23、在看事件分发机制  https://www.cnblogs.com/huihuizhang/p/7633552.html
24、IntentFilter的作用
25、app如何开启一个进程
26、进程保活,
27、自定义一个内容提供者。
28、屏幕旋转生命周期
29、EventBus的原理,Recyclerview的原理。














你可能感兴趣的:(面试题系列)