Android 同花顺面经
文章目录
一面
- Android组件化搭建使用接口层路由有什么缺点?
- 如果更改接口的话,其他的依赖的moudle都得改
- 说说kotlin和java的区别?
- Java是支持面向对象的编程,Kotlin是支持面向对象支持函数式编程
- Kotlin允许用户创建扩展函数,Java不支持任何扩展函数
- Kotlin使用var val 来定义变量
- Kotlin拥有很强大的Lambda表达式
- Kotlin 程序不需要分号,而 Java 程序需要分号
- 语言脚本功能允许您直接在 Gradle 构建脚本中使用 Kotlin,而 Java 不提供语言脚本功能。
- Kotlin 中没有空变量或对象,空变量或对象是 Java 语言的一部分。
- 假如老年代和新生代有互相引用,他使用标记清除怎么处理?
- 只需要在新生代上建立一个全局的数据结构,这个数据结构将老年代划分为若干个小块,每次都只记录老年代中的哪一块内存存在跨代引用。此后每当发生Minor GC时,只有包含了跨代引用的那一小块内存才会被加入到GC Roots中进行扫描。
- 新生代维护一个卡表,一个卡页内存中通常包含不止一个对象,只要卡页内某个对象的字段存在跨代指针,那就将对应卡表数组对应位置上的元素标示为1,称之为Dirty,没有则标示为0,称之为Clean。在垃圾收集时,只需要筛选出卡表中变脏的元素,就能够找到对应卡页内存块中包含的跨代指针,将其加入到GC Roots中一并扫描。
- 跨代引用、记忆集、卡表
- 实例.getClass() 与ClassForName.(类的全限定名)在执行过程中有什么区别?
- 出现的时期不同:Class.forname()在运行时加载;Class.class和对象名.getClass()是在编译时加载
- Class c = Class.class,是Class的class属性,Class c = c.getClass()则是通过对象获得类Class.forname(“全限定类名”),在运行时加载,对类进行加载,使用反射
- AIDL的具体实现步骤,sub对象是什么角色?
- 新建一个IImoocAIDL.aidl文件作文服务端,rebuild一下,自动生成IImoocAIDL.java的接口文件。
- 自动生成的AIDL文件,里面有
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: F:\\AS for android\\AIDLTest\\aidlclient\\src\\main\\aidl\\com\\mecury\\aidltest\\IImoocAIDL.aidl
*/
package com.mecury.aidltest;
// Declare any non-default types here with import statements
public interface IImoocAIDL extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.mecury.aidltest.IImoocAIDL {
private static final java.lang.String DESCRIPTOR = "com.mecury.aidltest.IImoocAIDL"; //Binder的唯一标识
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.mecury.aidltest.IImoocAIDL interface,
* generating a proxy if needed.
*/
//将服务端的Binder对象转换成客户需要的AIDL对象,转换区分进程,客户端服务端位于同一进程,返回服务端的
//Stub对象本身;否则返回的是系统的封装后的Stub.proxy对象。
public static com.mecury.aidltest.IImoocAIDL asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.mecury.aidltest.IImoocAIDL))) {
return ((com.mecury.aidltest.IImoocAIDL) iin);
}
return new com.mecury.aidltest.IImoocAIDL.Stub.Proxy(obj);
}
//返回当前Binder对象
@Override
public android.os.IBinder asBinder() {
return this;
}
//运行在服务端的Binder线程池中
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_add: {
data.enforceInterface(DESCRIPTOR);
//读取客户端传递过来再data中存储的方法的参数
int _arg0;
_arg0 = data.readInt();
int _arg1;
_arg1 = data.readInt();
//调用方法
int _result = this.add(_arg0, _arg1);
//将计算结果写入reply中
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags); //向Transact传递数据
}
//代理类,运行在客户端
private static class Proxy implements com.mecury.aidltest.IImoocAIDL {
private android.os.IBinder mRemote; //声明一个IBinder对象
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
//返回当前Binder对象
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
//客户端调用此方法,传递进来num1和num2两个参数,
@Override
public int add(int num1, int num2) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
//向_data中写入参数
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(num1);
_data.writeInt(num2);
//通过transact方法向服务端传递参数,并调用了方法,返回的结果写入_reply中
mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
//标识位
static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
//计算num1 + num2
public int add(int num1, int num2) throws android.os.RemoteException;
}
- 在服务端新建一个Service用来监听客户端连接请求
private IBinder iBinder = new IImoocAIDL.Stub(){
@Override
public int add(int num1, int num2) throws RemoteException {
Log.e("TAG","收到了来自客户端的请求" + num1 + "+" + num2 );
return num1 + num2;
}
};
- <font style="color:rgb(79, 79, 79);">在AndroidMainfest.xml注册Service</font>
- <font style="color:rgb(79, 79, 79);">客户端绑定服务并调用服务端方法</font>
private ServiceConnection conn = new ServiceConnection() {
//绑定服务,回调onBind()方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iImoocAIDL = IImoocAIDL.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
iImoocAIDL = null;
}
};
:::info
sub是extends Binder类,相当于可以进行跨进程通信,implement 业务类。本身也是一个抽象类
:::
- 谈谈你对window和Activity和DecoView的关系的理解
:::info
Activity就像个控制器,不负责视图部分。Window像个承载器,装着内部视图。DecorView就是个顶层视图,是所有View的最外层布局。ViewRoot像个连接器,负责沟通,通过硬件的感知来通知视图,进行用户之间的交互。
推荐阅读:简析 Window、Activity、DecorView 以及 ViewRoot 之间的错综关系
:::
- AIDL与Messenger、Binder区别
:::info
- 只有当你允许来自不同的客户端访问你的服务并且需要处理多线程问题时你才必须使用AIDL
- 如果进程间的通信来自同一应用,应该使用Binder
- 如果进程间的通信不需要处理多线程,应该使用Messenger
- Messenger不适用大量并发的请求:Messenger以串行的方式来处理客户端发来的消息,如果大量的消息同时发送到服务端,服务端仍然只能一个个的去处理。
- Messenger主要是为了传递消息:对于需要跨进程调用服务端的方法,这种情景不适用Messenger。
- Messenger的底层实现是AIDL,系统为我们做了封装从而方便上层的调用。
- AIDL适用于大量并发的请求,以及涉及到服务端端方法调用的情况
:::