2024年最全征服面试官系列: Binder 核心机制和进程间通信,你都理解了吗?,2024年最新安卓 高级面试

最后,面试前该准备哪些资源复习?

其实客户端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

这里再分享一下我面试期间的复习路线:(以下体系的复习资料是我从各路大佬收集整理好的)

《Android开发七大模块核心知识笔记》

面试字节两轮后被完虐,字节面试官给你的技术面试指南,请查收

面试字节两轮后被完虐,字节面试官给你的技术面试指南,请查收

《960全网最全Android开发笔记》

面试字节两轮后被完虐,字节面试官给你的技术面试指南,请查收

《379页Android开发面试宝典》

历时半年,我们整理了这份市面上最全面的安卓面试题解析大全
包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

客户端的代码就是通过绑定远程服务,然后获取到服务的Binder代理,来查询学生成绩。可见,使用Binder实现进程间通信是非常简单的,可以说简单的有点出乎所料。那我们之前写的AIDL是什么呢?AIDL生成的那一堆是什么玩意儿?我们且往下看。

三、代理模式优化Binder使用


虽然上一章中的代码已经非常简单了,但是还是有可以优化的空间。我们可以通过设计模式来进行优化,让代码更加简洁。

首先需要定义一个接口查询成绩的接口IGradeInterface,代码如下:

public interface IGradeInterface {

// 查询成绩接口

int getStudentGrade(String name);

}

1.服务端代码优化

接着,对服务端的代码进行优化。我们实现一个自定义的GradeBinder,并实现上述接口,代码如下:

public class GradeBinder extends Binder implements IGradeInterface {

@Override

public int getStudentGrade(String name) {

return StudentMap.getStudentGrade(name);

}

@Override

protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {

if (code == REQUEST_CODE) {

String name = data.readString();

int studentGrade = getStudentGrade(name);

if (reply != null)

reply.writeInt(studentGrade);

return true;

}

return super.onTransact(code, data, reply, flags);

}

}

上述代码将查询成绩的相关逻辑从Service搬到了GradeBinder中。因此,此时Service中只需要在onBind的时候返回GradeBinder的实例即可。代码如下:

public class GradeService extends Service {

public static final int REQUEST_CODE=1000;

@Nullable

@Override

public IBinder onBind(Intent intent) {

return new GradeBinder();

}

}

2.客户端代码优化

客户端优化的思路是在连接到远程服务时候实例化一个代理类,代理类持有Binder,让代理类行使Binder的权利。首先来看代理类的代码实现:

public class BinderProxy implements IGradeInterface {

// 被代理的Binder

private final IBinder mBinder;

// 私有化构造方法

private BinderProxy(IBinder binder) {

mBinder = binder;

}

// 通过Binde读取成绩

@Override

public int getStudentGrade(String name) {

Parcel data = Parcel.obtain();

Parcel reply = Parcel.obtain();

int grade = 0;

data.writeString(name);

try {

if (mBinder == null) {

throw new IllegalStateException(“Need Bind Remote Server…”);

}

mBinder.transact(REQUEST_CODE, data, reply, 0);

grade = reply.readInt();

} catch (RemoteException e) {

e.printStackTrace();

}

return grade;

}

// 实例化Binder代理类的对象

public static IGradeInterface asInterface(IBinder iBinder) {

if (iBinder == null) {

return null;

}

if (iBinder instanceof IGradeInterface) {

LogUtils.e(“当前进程”);

// 如果是同一个进程的请求,则直接返回Binder

return (IGradeInterface) iBinder;

} else {

LogUtils.e(“远程进程”);

// 如果是跨进程查询则返回Binder的代理对象

return new BinderProxy(iBinder);

}

}

}

BinderProxy类的构造方法被设置成了private。同时提供了一个asInterface方法中,这个方法通过判断Binder是不是IGradeInterface类型从而确定是不是跨进程的通信。如果不是跨进程通信,则返回当前这个Binder,否则就返回Binder的这个代理类。

接下来客户端连接上远程服务的时候使用BinderProxy获取Binder或者BinderProxy实例。代码如下:

public class BinderProxyActivity extends BaseViewBindingActivity {

// 此处可能是BinderProxy也可能是GradeBinder

private IGradeInterface mBinderProxy;

private final ServiceConnection mServiceConnection = new ServiceConnection() {

@Override

public void onServiceConnected(ComponentName componentName, IBinder iBinder) {

// 连接服务成功,根据是否跨进程获取BinderProxy或者GradeBinder实例

mBinderProxy = BinderProxy.asInterface(iBinder);

}

@Override

public void onServiceDisconnected(ComponentName componentName) {

mBinderProxy = null;

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

binding.btnBindService.setOnClickListener(view -> bindGradeService());

// 查询学生成绩点击事件,通过mBinderProxy查询成绩

binding.btnFindGrade.setOnClickListener(view -> ToastUtils.showShort("Anna grade is " + mBinderProxy.getStudentGrade(“Anna”)));

}

// 绑定服务

private void bindGradeService() {

String action = “android.intent.action.server.gradeservice”;

Intent intent = new Intent(action);

intent.setPackage(getPackageName());

bindService(intent, mServiceConnection, BIND_AUTO_CREATE);

}

}

可以看到,此时的代码相比第一章的代码整洁了不少。但是,代码写起来似乎还没有第一章中的方便。主要是因为要我们增加一个IGradeInterface接口,还要自定义一个GradeBinder,同时,还需要写代理类的相关代码,感觉非常繁琐。那么有没有办法让代码简洁,写起来还不繁琐呢?答案是肯定的,使用AIDL就可以实现。

四、AIDL


AIDL是Android Interface Description Languaged 简写。用于描写客户端/服务端通信接口的一种描述语言。提起AIDL相信很多人都会觉得头大,定义一个AIDL接口,生成了那么多不知所云的代码,看起来简直就是灾难。先别担心,如果你看懂了第三章的内容,那么其实你已经完全掌握了AIDL。没错,说白了AIDL生成的那一坨代码其实就是我们第三章中写的代码。即AIDL的原理其实就是使用了代理模式对Binder的使用进行了优化,使用AIDL保证了代码的整洁,同时也省去了自己编写繁琐的代理类相关代码。

关于AIDL的使用就非常简单了。

1.创建AIDL接口

首先,在要创建AIDL的目录上右键->New->AIDL->AIDl File 来创建一个AIDL文件,如下图所示:

创建一个名为IGradeService的AIDL文件,并添加一个getStudentGrade的方法。代码如下:

// IGradeService.aidl

package com.zhpan.sample.binder.aidl;

// Declare any non-default types here with import statements

interface IGradeService {

/**

  • Demonstrates some basic types that you can use as parameters

  • and return values in AIDL.

*/

void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,

double aDouble, String aString);

int getStudentGrade(String name);

}

接着Rebuild一下项目后IDE就会自动生成AIDL的代码了。

2.AIDL生成的代码

在项目的build目录下com.zhpan.sample.binder.aidl包中会看到自动生成的一个名为IGradeService的接口,代码如下:

// 这个接口相当于上一章中的IGradeInterface接口

public interface IGradeService extends android.os.IInterface {

// Stub是一个Binder,相当于上一章中的GradeBinder

public static abstract class Stub extends android.os.Binder

implements com.zhpan.sample.binder.aidl.IGradeService {

private static final java.lang.String DESCRIPTOR = “com.zhpan.sample.binder.aidl.IGradeService”;

public Stub() {

this.attachInterface(this, DESCRIPTOR);

}

public static IGradeService asInterface(android.os.IBinder obj) {

if ((obj == null)) {

return null;

}

android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);

if (((iin != null) && (iin instanceof com.zhpan.sample.binder.aidl.IGradeService))) {

// 如果是当前进程则直接返回当前Binder对象

return ((com.zhpan.sample.binder.aidl.IGradeService) iin);

}

// 跨进程则返回Binder的代理对象

return new com.zhpan.sample.binder.aidl.IGradeService.Stub.Proxy(obj);

}

@Override public android.os.IBinder asBinder() {

return this;

}

@Override

public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)

throws android.os.RemoteException {

java.lang.String descriptor = DESCRIPTOR;

switch (code) {

case INTERFACE_TRANSACTION: {

reply.writeString(descriptor);

return true;

}

case TRANSACTION_basicTypes: {

data.enforceInterface(descriptor);

int _arg0;

_arg0 = data.readInt();

long _arg1;

_arg1 = data.readLong();

boolean _arg2;

_arg2 = (0 != data.readInt());

float _arg3;

_arg3 = data.readFloat();

double _arg4;

_arg4 = data.readDouble();

java.lang.String _arg5;

_arg5 = data.readString();

this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);

reply.writeNoException();

return true;

}

case TRANSACTION_getStudentGrade: {

data.enforceInterface(descriptor);

java.lang.String _arg0;

_arg0 = data.readString();

int _result = this.getStudentGrade(_arg0);

reply.writeNoException();

reply.writeInt(_result);

return true;

}

default: {

return super.onTransact(code, data, reply, flags);

}

}

}

// Binder的代理类,相当于上一章中的BinderProxy

private static class Proxy implements com.zhpan.sample.binder.aidl.IGradeService {

private android.os.IBinder mRemote;

Proxy(android.os.IBinder remote) {

mRemote = remote;

}

@Override public android.os.IBinder asBinder() {

return mRemote;

}

public java.lang.String getInterfaceDescriptor() {

return DESCRIPTOR;

}

@Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,

double aDouble, java.lang.String aString) throws android.os.RemoteException {

android.os.Parcel _data = android.os.Parcel.obtain();

android.os.Parcel _reply = android.os.Parcel.obtain();

try {

_data.writeInterfaceToken(DESCRIPTOR);

_data.writeInt(anInt);

_data.writeLong(aLong);

_data.writeInt(((aBoolean) ? (1) : (0)));

_data.writeFloat(aFloat);

_data.writeDouble(aDouble);

_data.writeString(aString);

boolean _status = mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);

if (!_status && getDefaultImpl() != null) {

getDefaultImpl().basicTypes(anInt, aLong, aBoolean, aFloat, aDouble, aString);

return;

}

_reply.readException();

} finally {

_reply.recycle();

_data.recycle();

}

}

@Override public int getStudentGrade(java.lang.String name)

throws android.os.RemoteException {

android.os.Parcel _data = android.os.Parcel.obtain();

android.os.Parcel _reply = android.os.Parcel.obtain();

int _result;

try {

_data.writeInterfaceToken(DESCRIPTOR);

_data.writeString(name);

boolean _status = mRemote.transact(Stub.TRANSACTION_getStudentGrade, _data, _reply, 0);

if (!_status && getDefaultImpl() != null) {

return getDefaultImpl().getStudentGrade(name);

}

_reply.readException();

_result = _reply.readInt();

} finally {

_reply.recycle();

_data.recycle();

}

return _result;

}

public static com.zhpan.sample.binder.aidl.IGradeService sDefaultImpl;

}

static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);

static final int TRANSACTION_getStudentGrade = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);

public static boolean setDefaultImpl(com.zhpan.sample.binder.aidl.IGradeService impl) {

结尾

最后,针对上面谈的内容,给大家推荐一个Android资料,应该对大家有用。

首先是一个知识清单:(对于现在的Android及移动互联网来说,我们需要掌握的技术)

泛型原理丶反射原理丶Java虚拟机原理丶线程池原理丶
注解原理丶注解原理丶序列化
Activity知识体系(Activity的生命周期丶Activity的任务栈丶Activity的启动模式丶View源码丶Fragment内核相关丶service原理等)
代码框架结构优化(数据结构丶排序算法丶设计模式)
APP性能优化(用户体验优化丶适配丶代码调优)
热修复丶热升级丶Hook技术丶IOC架构设计
NDK(c编程丶C++丶JNI丶LINUX)
如何提高开发效率?
MVC丶MVP丶MVVM
微信小程序
Hybrid
Flutter

接下来是资料清单:(敲黑板!!!


1.数据结构和算法

2.设计模式

3.全套体系化高级架构视频;七大主流技术模块,视频+源码+笔记

4.面试专题资料包(怎么能少了一份全面的面试题总结呢~)

不论遇到什么困难,都不应该成为我们放弃的理由!共勉~

如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

MVVM

微信小程序
Hybrid
Flutter

[外链图片转存中…(img-og8Nuxvi-1715897767753)]

接下来是资料清单:(敲黑板!!!


1.数据结构和算法

[外链图片转存中…(img-YY0tG7Dm-1715897767753)]

2.设计模式

[外链图片转存中…(img-7pB4HlNx-1715897767754)]

3.全套体系化高级架构视频;七大主流技术模块,视频+源码+笔记

[外链图片转存中…(img-VqmtWFx8-1715897767754)]

4.面试专题资料包(怎么能少了一份全面的面试题总结呢~)

[外链图片转存中…(img-NVrZEf08-1715897767754)]

不论遇到什么困难,都不应该成为我们放弃的理由!共勉~

如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。

[外链图片转存中…(img-y906LMyy-1715897767755)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 21
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值