写点什么

成功获得字节跳动月薪 20+ 的 Android 岗 offer,看看面试都问了些什么

用户头像
Android架构
关注
发布于: 2021 年 11 月 03 日

private WeakReference<MainActivity> activityWeakReference;


private MyHandler myHandler;


static class MyHandler extends Handler {


private MainActivity activity;


MyHandler(WeakReference<MainActivity> ref) {


this.activity = ref.get();


}


@Override


public void handleMessage(Message msg) {


super.handleMessage(msg);


switch (msg.what) {


case 1:


//需要做判空操作


if (activity != null) {


activity.mTextView.setText("new Value");


}


break;


default:


Log.i(TAG, "handleMessage: default ");


break;


}


@Override


protected void onCreate(Bundle savedInstanceState) {


super.onCreate(savedInstanceState);


setContentView(R.layout.activity_main);


//在 onCreate 中初始化


activityWeakReference = new WeakReference<MainActivity>(this);


myHandler = new MyHandler(activityWeakReference);


myHandler.sendEmptyMessage(1);


mTextView = (TextView) findViewById(R.id.tv_test);


}


参考博文:http://blog.csdn.net/ucxiii/article/details/50972747


3.Android IPC:Binder 原理




1.在 Activity 和 Service 进行通讯的时候,用到了 Binder。


o1.当属于同个进程我们可以继承 Binder 然后在 Activity 中对 Service 进行操作


o2.当不属于同个进程,那么要用到 AIDL 让系统给我们创建一个 Binder,然后在 Activity 中对远端的 Service 进行操作。


2.系统给我们生成的 Binder:


o1.Stub 类中有:接口方法的 id,有该 Binder 的标识,有 asInterface(IBinder)(让我们在 Activity 中获取实现了 Binder 的接口,接口的实现在 Service 里,同进程时候返回 Stub 否则返回 Proxy),有 onTransact()这个方法是在不同进程的时候让 Proxy 在 Activity 进行远端调用实现 Activity 操作 Service


o2.Proxy 类是代理,在 Activity 端,其中有:IBinder mRemote(这就是远端的 Binder),两个接口的实现方法不过是代理最终还是要在远端的 onTransact()中进行实际操作。


3.哪一端的 Binder 是副本,该端就可以被另一端进行操作,因为 Binder 本体在定义的时候可以操作本端的东西。所以可以在 Activity 端传入本端的 Binder,让 Service 端对其进行操作称为 Listener,可以用 RemoteCallbackList 这个容器来装 Listener,防止 Listener 因为经历过序列化而产生的问题。


4.当 Activity 端向远端进行调用的时候,当前线程会挂起,当方法处理完毕才会唤醒。


5.如果一个 AIDL 就用一个 Service 太奢侈,所以可以使用 Binder 池的方式,建立一个 AIDL 其中的方法是返回 IBinder,然后根据方法中传入的参数返回具体的 AIDL。


6.IPC 的方式有:Bundle(在 Intent 启动的时候传入,不过是一次性的),文件共享(对于 SharedPreference 是特例,因为其在内存中会有缓存),使用 Messenger(其底层用的也是 AIDL,同理要操作哪端,就在哪端定义 Messenger),AIDL,ContentProvider(在本进程中继承实现一个 ContentProvider,在增删改查方法中调用本进程的 SQLite,在其他进程中查询),Socket


4.描述一次跨进程通讯




1.client、proxy、serviceManager、BinderDriver、impl、service


2.client 发起一个请求 service 信息的 Binder 请求到 BinderDriver 中,serviceManager 发现 BinderDiriver 中有自己的请求 然后将 clinet 请求的 service 的数据返回给 client 这样完


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


成了一次 Binder 通讯


3.clinet 获取的 service 信息就是该 service 的 proxy,此时调用 proxy 的方法,proxy 将请求发送到 BinderDriver 中,此时 service 的 Binder 线程池循环发现有自己的请求,然后用 impl 就处理这个请求最后返回,这样完成了第二次 Binder 通讯


4.中间 client 可挂起,也可以不挂起,有一个关键字 oneway 可以解决这个


二、算法题


=====


1.lc 里最长上升子序列的变形题。




2.实现输入英文单词联想的功能




3.矩阵旋转,要求空间复杂度 O(1)




4.无序的数组的中位数。要求时间复杂度尽可能的小




三、计算机网络


=======


1.tcp 怎么保证数据包有序




  1. 主机每次发送数据时,TCP 就给每个数据包分配一个序列号并且在一个特定的时间内等待接收主机对分配的这个序列号进行确认,

  2. 如果发送主机在一个特定时间内没有收到接收主机的确认,则发送主机会重传此数据包。

  3. 接收主机利用序列号对接收的数据进行确认,以便检测对方发送的数据是否有丢失或者乱序等,

  4. 接收主机一旦收到已经顺序化的数据,它就将这些数据按正确的顺序重组成数据流并传递到高层进行处理。


2.tcp 和 udp 的异同




TCP 是面向流的可靠数据传输连接


UDP 是面向数据包的不可靠无连接


3.tcp 怎么保证可靠性




差错检验机制,反馈机制,重传机制,引入序号,滑动窗口协议,选择重传


4.tcp 中 拥塞避免 和 流量控制 机制




拥塞避免和流量控制这两种机制很像,但是流量控制是由接收方的接受能力也就是接收窗口所决定的,如果接收窗口够大,以动态调整发送窗口的大小调整发送速度


拥塞避免主要由网络情况所限制,网络情况良好,则加大发送速率,网络状态差(冗余 ACK 和丢包)则降低发送速率(慢启动,拥塞控制,快恢复,快重传)RENO,BBR


5.tcp 四次挥手的详细解释




tcp 四次挥手其实可以分为两个阶段


第一:


客户端至服务器的半双工连接关闭


客户端向服务器发送 FIN 信号,进入 FIN_WAIT1 的状态,等待服务器的 ACK 信号


收到服务器的 ACK 后,进入 FIN_WAIT2


第二:


服务器至客户端的半双工连接关闭


客户端收到服务器发来的 FIN 后,发送 ACK,并进入 TIME_WAIT,等待 2msl,若无异常,则客户端认为连接成功关闭


服务器收到客户端发来的 ACK 后,关闭连接


四次挥手之后为什么还要等待 2msl


MSL 是报文最大生存时间


1 是因为有可能客户端发往服务器的 ACK 丢失,服务器并不知道客户端已经确认关闭,这时候客户端的关闭会导致服务器端无法正常关闭


2 是为了保证连接中的报文都已经传递。假如短时间关闭又重新实现一个 TCP 还连到了同个端口上,旧连接中尚未消失的数据就会被认为是新连接的数据。


浏览器从输入网址到显示出网页的全过程


1.输入网址或者 ip。


2.如果输入的是网址,首先要查找域名的 ip 地址


第一步会在浏览器缓存中查找,如果没有,转至查询系统缓存,如果还是没有,发送请求给路由器,路由器首先会在自身的缓存中查找,如果还是没有,向 ips 发出请求,查询 ips 中的 dns 缓存,如果还是没有递归向上查询直至根服务器。


.浏览器与 ip 机器之间建立 TCP 连接(三次握手)(HTTP)或者在 TCP 上进一步建立 SSL/TLS 连接(HTTPS)


接下来就是发送 HTTP 报文啥的了


GET,POST,DELETE,PUT。


滑动窗口机制的原理和理解


GBN 协议,回退 N 步协议,这是对停等协议的改进,因为停等协议的传输效率非常低下。每次可发送的数据为 N,基数为 base,小于 base 的数据已经发送并且确认,base 是最小的已发送未确认的报文序号。在接收端同样也有一个接收窗口,(解释)GBN 采用的是累计确认方式,这时候说一下选择重传机制。再说一下 TCP 中既不是 GBN 也不是 SR,而是 GBN 和 SR 的综合体。


N 的大小必须报文序列编号的一半,否则接收端对报文的确认可能发生混淆


Https 原理和实现


cookie 和 session 的区别是什么


由于 HTTP 协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户


cookie 存在本地的上的


session 是存在服务器上的


通俗讲,Cookie 是访问某些网站以后在本地存储的一些网站相关的信息,下次再访问的时候减少一些步骤。另外一个更准确的<u style="text-decoration: none; border-bottom: 1px dashed grey;">说法</u>是:Cookies 是服务器在本地机器上存储的小段文本并随每一个请求发送至同一个服务器,是一种在客户端保持状态的方案。


Session 是存在服务器的一种用来存放用户数据的类 HashTable 结构。


二者都用来保持用户的状态,cookie 可更改,对服务器来说并不安全,服务器常见做法有这两种


1.把 session 加密后放入浏览器的 cookie 中,浏览器重连后将加密的 session 发给服务器


2.cookie 中存储着 session 的 id,浏览器重连时只需要发送 session_id'即可


四、操作系统




进程和线程的区别


进程就是包换上下文切换的程序执行时间总和 = CPU 加载上下文+CPU 执行+CPU 保存上下文


线程是什么呢?


进程的颗粒度太大,每次都要有上下的调入,保存,调出。如果我们把进程比喻为一个运行在电脑上的软件,那么一个软件的执行不可能是一条逻辑执行的,必定有多个分支和多个程序段,就好比要实现程序 A,实际分成 a,b,c 等多个块组合而成。那么这里具体的执行就可能变成:


程序 A 得到 CPU =》CPU 加载上下文,开始执行程序 A 的 a 小段,然后执行 A 的 b 小段,然后再执行 A 的 c 小段,最后 CPU 保存 A 的上下文。


这里 a,b,c 的执行是共享了 A 的上下文,CPU 在执行的时候没有进行上下文切换的。这**里的 a,b,c 就是线程,也就是说线程是共享了进程的上下文环境,的更为细小的 CPU 时间段。


五、设计模式


======


简述一个设计模式的概念,并简要谈谈 framework 层哪些地方用到了什么设计模式


单例模式:单例模式是一种对象创建模式,它用于产生一个对象的具体实例,它可以确保系统中一个类只产生一个实例。


适配器模式:将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)


装饰模式:动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。装饰模式是一种对象结构型模式。


使用场景:


1.在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。


2.当不能采用继承的方式对系统进行扩展或者采用继承不利于系统扩展和维护时可以使用装饰模式。


优点:


1.对于扩展一个对象的功能,装饰模式比继承更加灵活,不会导致类的个数急剧增加。


2.可以通过一种动态地方式来扩展一个对象的功能。


3.可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合。


实际运用:


Android 中 Context 类的实现


外观模式: 主要目的在于让外部减少与子系统内部多个模块的交互,从而让外部能够更简单得使用子系统。它负责把客户端的请求转发给子系统内部的各个模块进行处理。


使用场景:


1.当你要为一个复杂的子系统提供一个简单的接口时


2.客户程序与抽象类的实现部分之前存在着很大的依赖性


3.当你需要构建一个层次结构的子系统时

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
成功获得字节跳动月薪20+的Android岗offer,看看面试都问了些什么