最后,面试前该准备哪些资源复习?
其实客户端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。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行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!