码仔,今天就给大家带来了《每日一道面试题》的第九期:
01
理解Activity View window的关系
Activity像一个工匠(控制单元),Window像窗户(承载模型),View像窗花(显示视图)LayoutInflater像剪刀,Xml配置像窗花图纸。
Activity构造的时候会初始化一个Window,准确的说是PhoneWindow。
这个PhoneWindow有一个“ViewRoot”,这个“ViewRoot”是一个View或者说ViewGroup,是最初始的根视图。
“ViewRoot”通过addView方法来一个个的添加View。比如TextView,Button等
这些View的事件监听,是由WindowManagerService来接受消息,并且回调Activity函数。比如onClickListener,onKeyDown等
02
Android进程间通讯的几种姿势
进程间通信即IPC,英文全称Inter-Process Communication,是指进程间数据交互的过程. Android底层是基于Linux,而Linux基于安全考虑,是不允许两个进程间直接操作对方的数据,这就是进程隔离. 六种常用姿势:
Bundle
文件共享
AIDL
Messenger
ContentProvider
Socket
03
谈谈对责任链模式的理解
使很多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
何时使用:
有许多对象可以处理用户请求,希望程序在运行期间自动确定处理用户的那个对象。
希望用户不必明确指定接收者的情况下,想多个接受者的一个提交请求
程序希望动态的指定可处理用户请求的对象集合
优点:
低耦合
可以动态的添加删除处理者或重新指派处理者的职责
可以动态改变处理者之间的先后顺序
通常来说,一个纯粹的责任链是先传给第一个处理,如果处理过了,这个请求处理就此结束,如果没有处理,再传给下一个处理者。
比如我们有一个数学公式,有一个整数输入,要求小于0时返回绝对值,其次,小于10的时候返回他的二次幂,否则,返回他本身:
首先我们要定义一个接口(处理者),来描述他们共有的行为:
public interface Handler {
int handleRequest(int n);
void setNextHandler(Handler next);
}
然后是具体的处理者
public class Handler1 implements Handler {
private Handler next;
@Override
public int handleRequest(int n) {
if(n<0) return -n;
else{
if(next==null)
throw new NullPointerException("next 不能为空");
return next.handleRequest(n);
}
}
@Override
public void setNextHandler(Handler next) {
this.next = next;
}
}
public class Handler2 implements Handler {
private Handler next;
@Override
public int handleRequest(int n) {
if(n<10) return n*n;
else{
if(next==null)
throw new NullPointerException("next 不能为空");
return next.handleRequest(n);
}
}
@Override
public void setNextHandler(Handler next) {
this.next = next;
}
}
public class Handler3 implements Handler {
private Handler next;
@Override
public int handleRequest(int n) {
if(n<=Integer.MAX_VALUE) return n;
else{
if(next==null)
throw new NullPointerException("next 不能为空");
return next.handleRequest(n);
}
}
@Override
public void setNextHandler(Handler next) {
this.next = next;
}
}
public class TestUse {
public static void main(String args[]){
Handler h1,h2,h3;
h1 = new Handler1();
h2 = new Handler2();
h3 = new Handler3();
h1.setNextHandler(h2);
h2.setNextHandler(h3);
System.out.println(h1.handleRequest(-1));
System.out.println(h1.handleRequest(5));
System.out.println(h1.handleRequest(9999));
}
}
此处责任链中的具体处理者的顺序是不能重设的,否则可能会引发错误,但更多的情况是完全可以随意更改他们的位置的,就上例中,只要把if中的条件重新设置(各自独立,不相互依赖),就可以了。
我们使用责任链模式的时候,不一定非得某一处理者处理后就得终止请求的传递,如果有其他需求,我们依然可以继续传递这个请求到下一个具体的处理者。
04
Https三次握手四次挥手
三次握手:在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。(1)第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;(2)第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器 进入SYN_RECV状态;(3)第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入 ESTABLISHED状态,完成三次握手。完成三次握手,客户端与服务器开始传送数据.
四次分手:(1)客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送。(2)服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。(3)服务器B关闭与客户端A的连接,发送一个FIN给客户端A。(4)客户端A发回ACK报文确认,并将确认序号设置为收到序号加1。
05
Android的存储方式
Android提供了5中存储数据的方式,分别是以下几种:
1、使用Shared Preferences存储数据,用来存储key-value,pairs格式的数据,它是一个轻量级的键值存储机制,只可以存储基本数据类型。
2、使用文件存储数据,通过FileInputStream和FileOutputStream对文件进行操作。在Android中,文件是一个应用程序私有的,一个应用程序无法读写其他应用程序的文件。
3、使用SQLite数据库存储数据,Android提供的一个标准数据库,支持SQL语句。
4、使用Content Provider存储数据,是所有应用程序之间数据存储和检索的一个桥梁,它的作用就是使得各个应用程序之间实现数据共享。它是一个特殊的存储数据的类型,它提供了一套标准的接口用来获取数据,操作数据。系统也提供了音频、视频、图像和个人信息等几个常用的Content Provider。如果你想公开自己的私有数据,可以创建自己的Content Provider类,或者当你对这些数据拥有控制写入的权限时,将这些数据添加到Content Provider中实现共享。外部访问通过Content Resolver去访问并操作这些被暴露的数据。
5、使用网络存储数据
06
结束语
如果你有好的答案可以提交至:
https://github.com/codeegginterviewgroup/CodeEggDailyInterview
往期文章:
《每日一道面试题》第一期
《每日一道面试题》 第二期
《每日一道面试题》 第三期
《每日一道面试题》第四期
《每日一道面试题》第五期
《每日一道面试题》 第六期
《每日一道面试题》 第七期
《每日一道面试题》 第八期
专属社群:
《这件事情,我终于想明白了》
今日问题:
大家想看什么类型的文章?