Android完整详细阿里腾讯面试题含答案(二)

1,022 阅读10分钟

1、配置改变时,会导致Activity被杀死并且重新创建,那么我们要如何避免该情况的发生?

第一种解决思路:设置配置文件中Activity的configChanges属性。 我们可在AndroidManifest.xml中对应的Activity中设置android:configChanges="orientation|screenSize"。再次旋转屏幕,Activity不会被杀死重建,会直接调用onConfigurationChanged。因此,在这种情况下,我们只需要指定configChanges属性,并且重写onConfigurationChanged()方法即可。

2、当系统内存不足时,会将一些低优先级的Activity回收,如何去将其恢复到销毁前的状态? 

 Activity重新创建时会调用onRestoreInstanceState(注意:此时调用该方法是在onStart之后),并且将onSaveInstanceState所保存的Bundle对象作为参数传到**onRestoreInstanceState(Bundle savedInstanceState)onCreate(Bundle savedInstanceState)**方法。我们也可以通过这两种方法来判断Activity是否被重建,并进行数据恢复。

3、如何去启动其他应用的Activity? 

首先我们先保证权限性,在有权限的条件下,通过隐式Intent进行目标Activity的IntentFilter匹配:

  • 一个intent只有同时匹配某个Activity的intent-filter中的action、category、data才算完全匹配,才能够启动该Activity。
  • 一个Activity可以有多个intent-filter,一个intent只需要成功匹配任意一组intent-filter,就可以启动该Activity。
  • action、category、data的匹配规则:

1.Intent中的Action必须能够和Activity过滤规则中的Action匹配.(这里的匹配是完全相等). 一个过滤规则中有多个action,那么只要Intent中的action能够和Activity过滤规则中的任何一个action相同即可匹配成功。

2.如果Intent中的存在category那么所有的category都必须和Activity过滤规则中的category相同。才能和这个Activity匹配。Intent中的category数量可能少于Activity中配置的category数量,但是Intent中的这category必须和Activity中配置的category相同才能匹配。

3.如果Intent中的存在data那么所有的data都必须和Activity过滤规则中的data相同。才能和这个Activity匹配。Intent中的data数量可能少于Activity中配置的data数量,但是Intent中的这data必须和Activity中配置的data相同才能匹配。

4、Fragment生命周期中涉及的方法及作用?

 Fragment完整的生命周期:onAttach(Fragment和Activity建立关联时调用) ——> onCreate(fragment初始化) ——> onCreateView(Fragment创建视图时调用) ——> onActivityCreated(与Fragment关联的Activity完成onCreate()之后调用)——>  onStart(正在启动,此时可见但是没处在前台,不可与用户交互) ——> onResume(获得焦点,可见且处于前台,可以进行活动) ——> onPause(正在停止,此时可以进行数据存储、停止动画等操作) ——> onDestroyView(布局移除时调用) ——> onDestroy(销毁) ——> onDetch(解除Fragment和Activity的关联)。

5、Activity与Fragment的关系?

Fragment可作为Activity的界面组成部分,可在Activity运行中动态的实现加入、移除和交换。

一个Activity可以拥有多个Fragment,一个Fragment也可以依附于多个Activity。

Activity的FragmentManager负责调用队列中的Fragment的生命周期方法,只要Fragment的状态与Activity的状态保持一致,宿主Activity的FragmentManager就会继续调用其他生命周期方法以保持Fragment和Activity的状态一致。

6、Service生命周期及启动方式?

生命周期:

onCreate():服务第一次被创建时调用。

onStartCommand():服务启动时调用。

onBind():服务被绑定时调用。

onUnBind():服务被解绑时调用。

onDestroy():服务停止时调用。

启动方式:

第一种启动方式:其他组件调用Context的StartService()方法启动一个Service,并回调服务中的onStartCommand()。如果服务之前没有创建,那么回调的顺序是onCreate() ——> onStartCommand()。服务启动之后会一直保持运行状态,直到stopService()或stopSelf()方法被调用,服务停止并回调onDestroy()。

第二种启动方式:其他组件调用Context的bindService()绑定一个Service,并回调服务中的onBind()方法,如果服务之前没有创建,那么回调的顺序是onCreate() ——> onBind()。之后,调用方可以获取到onBind()方法中返回的IBinder对象的实例,从而实现和服务进行通信。只要调用方和服务之间的连接没有断开,服务就会一直保持运行状态,直到调用了UnBindService()方法服务停止,回调顺序onUnBind() ——> onDestroy()。

7、Service和Activity如何进行通信?

Android:Activity与Fragment、Service之间的数据通信

8、常用的系统Service都有哪些?

9、Service中能否进行耗时操作?

Service默认并不会运行在子线程中,也不运行在一个独立的进程中,它同样执行在主线程中(UI线程)。也就是说,我们不要在Service中进行耗时操作,否则可能会出现主线程被阻塞(ANR)的情况。

10、AlarmManager实现定时功能的原理是?

通过调用AlarmManager的set()方法就可以设置一个定时任务,提供三个参数(工作类型,定时任务触发的时间,PendingIntent对象),其中PendingIntent对象是关键,调用它的getBoardcast()方法来获取一个能够执行广播的PendingIntent。当定时任务被触发时,广播接收器的onReceive()方法得以执行。即通过服务和广播的循环触发实现定时服务。

网络编程

1、三次挥手、四次挥手过程?

(1) 建立TCP连接:TCP的三次握手

步骤:客户端向服务端发送一个表示建立连接的报文段SYN报文段;一旦包含SYN报文段的IP数据报到达服务器主机,服务器从IP数据报中提取出TCP、SYN报文段,为该TCP连接分配需要的缓存和变量,并向客户端发送表示允许连接的报文段ACK;在收到ACK报文段之后,客户端也要给该连接分配缓存和变量,客户端向服务器再发送一个报文段ACK,表示对允许连接的报文段进行了确认,自此完成一次TCP连接。【第三次握手可以避免由于客户端延迟的请求连接的请求,使得服务端无故再次建立连接】

(2)解除TCP连接:TCP的四次挥手

步骤:由于TCP连接是全双工的,因此要解除连接我们要在每个方向都必须单独关闭。客户端在数据发送完毕后发送一个结束数据段FIN,服务端返回确认数据段ACK,在此结束了客户端到服务端的连接,然后客户端接收到服务端发送的FIN,且服务端也收到ACK之后,到此双方的数据通信就完全结束。一共需要四个步骤:服务器读通道关闭 -> 客户端写通道关闭 -> 客户机读通道通道关闭 -> 服务器写通道关闭。

2、Http、Https的区别?

  • HTTP(超文本传输协议):运行在TCP之上;传输的内容是明文。
  • HTTPS(安全为目标的HTTP):运行在SSL/TLS之上,SSL/TLS运行在TCP之上;传输的内容经过加密。

3、get、post的区别?

  • GET:当客户端要从服务器中读取某个资源时使用GET;一般用于获取/查询资源信息;GET参数通过URL传递,传递的参数是有长度限制,不能用来传递敏感信息
  • POST:当客户端给服务器提供信息较多时可以使用POST;POST会附带用户数据,一般用于更新资源信息;POST将请求参数封装在HTTP 请求数据中,可以传输大量数据,传参方式比GET更安全

JAVA基础

1、Java集合框架中有哪些类?都有什么特点?

可将Java集合框架大致可分为Set、List、Queue 和Map四种体系

  • Set:代表无序、不可重复的集合,常见的类如HashSet、TreeSet。
  • List:代表有序、可重复的集合,常见的类如动态数组ArrayList、双向链表LinkedList、可变数组Vector。
  • Map:代表具有映射关系的集合,常见的类如HashMap、LinkedHashMap、TreeMap。
  • Queue:代表一种队列集合。

2、ArrayList和LinkList的区别?

  • ArrayList的底层结构是数组,可用索引实现快速查找;是动态数组,相比于数组容量可实现动态增长。
  • LinkedList底层结构是链表,增删速度快;是一个双向循环链表,也可以被当作堆栈、队列或双端队列。

3、HashMap是如何扩容的?如何避免扩容?

  • HashMap几个默认值,初始容量为16、填充因子默认为0.75、扩容时容量翻倍。也就是说当HashMap中元素个数超过160.75=12时会把数组的大小扩展为216=32,然后重新计算每个元素在数组中的位置 。

  • 由于每次扩容还需要重新计算元素Hash值,损耗性能,所以建议在使用HashMap时,最好先估算Map的大小,设置初始值,避免频繁扩容。

4、synchronized和volatile的区别?

  • volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
  • volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
  • volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
  • volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
  • volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化

#操作系统

1、操作系统中进程和线程的区别?

  • 进程是操作系统分配和管理资源的单位,其拥有独立的地址空间,进程创建的开销比较大。
  • 线程是CPU调度和管理的单位,是CPU调度的最小单元,其创建的开销小,并且线程间共享地址空间。

2、进程的死锁?

概述

死锁是指多个进程因循环等待资源而造成无法执行的现象,它会造成进程无法执行,同时会造成系统资源的极大浪费。

产生

互斥使用:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

不可抢占:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

请求和保持:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

循环等待:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

解决死锁的方法

银行家算法:判断此次请求是否造成死锁若会造成死锁,否则拒绝该请求

鸵鸟算法:常用在极少发生死锁的情况

避免

通过合理的资源分配算法来确保永远不会形成环形等待的封闭进程链,即“如果一个进程的当前请求的资源会导致死锁,系统拒绝启动该进程;如果一个资源的分配会导致下一步的死锁,系统就拒绝本次的分配”。