写点什么

“我是培训 + 外包出来的 (1),flutter 与 android 混合开发

用户头像
Android架构
关注
发布于: 刚刚

//方法 1


public void setParted(int[] a){


int temp=0;


int border=-1;


for(int i=0;i<a.length;i++){


if(a[i]<0){


temp=a[i];


a[i]=a[border+1];


a[border+1]=temp;


border++;


}


}


for(int j=0;j<a.length;j++){


System.out.println(a[j]);


}


}


//方法 2


public void setParted1(int[] a,int left,int right){


if(left>=right||left==a.length||right==0){


for(int i=0;i<a.length;i++){


System.out.println(a[i]);


}


return ;


}


while(a[left]<0){


left++;


}


while(a[right]>=0){


right--;


}


if(left>=right||left==a.length||right==0){


for(int i=0;i<a.length;i++){


System.out.println(a[i]);


}


return;


}


swap(a,left,right);


left++;


right--;


setParted1(a,left,right);


}


private void swap(int a[],int left,int right){


int temp=0;


temp=a[left];


a[left]=a[right];


a[right]=temp;


}


public static void main(String[] args) {


int a[]={1,2,-1,-5,-6,7,-7,-10};


new PartTest().setParted1(a,0,a.length-1);


}


显然,第二种实现的难点比较高,不过只要此种满足条件。

第二面

1,bundle 的数据结构,如何存储,既然有了 Intent.putExtra,为啥还要用 bundle。


bundle 的内部结构其实是 Map,传递的数据可以是 boolean、byte、int、long、float、double、string 等基本类型或它们对应的数组,也可以是对象或对象数组。当 Bundle 传递的是对象或对象数组时,必须实现 Serializable 或 Parcelable 接口。


2,android 的 IPC 通信方式,是否使用过


这方面的资料比较多,也不方便阐述


3,Android 的多点触控如何传递 核心类


4,asynctask 的原理 AsyncTask 是对 Thread 和 Handler 的组合包装。


5,android 图片加载框架有哪些,对比下区别


6,图片框架的一些原理知识


7,其他的一些 Android 的模块化开发,热更新,组件化等知识。

三面;主流框架

在 Android 面试的时候,经常会被问到一些 Android 开发中用到的一些开发框架,如常见的网络请求框架 Retrofit/OkHttp,组件通信框架 EventBus/Dagger2,异步编程 RxJava/RxAndroid 等。结合本次面试,整理下上面的几个框架,大家可以拿去,面试备用


1. EventBus


EventBus 是一个 Android 发布/订阅事件总线,简化了组件间的通信,让代码更加简介,但是如果滥用 EventBus,也会让代码变得更加辅助。


面试 EventBus 的时候一般会谈到如下几点


(1)EventBus 是通过注解+反射来进行方法的获取的


(2)使用 ConcurrentHashMap 来保存映射关系?调用实体的构建:调用实体中对于 Object,也就是实际执行方法的对象不应该使用强引用而是应该使用弱引用,因为 Map 的 static 的,生命周期有可能长于被调用的对象,如果使用强引用就会出现内存泄漏的问题。


(3)方法的执行 使用 Dispatcher 进行方法的分派,异步则使用线程池来处理,同步就直接执行,而 UI 线程则使用 MainLooper 创建一个 Handler,投递到主线程中去执行。


2.Retrofit


要明确 EventBus 中最核心的,就是动态代理技术。


Java 中的动态代理:


首先动态代理是区别于静态代理的,代理模式中需要代理类和实际执行类同时实现一个相同的接口,并且在每个接口定义的方法前后都要加入相同的代码,这样有可能很多方法代理类都需要重复。而动态代理就是将这个步骤放入运行时的过程,一个代理类只需要实现 InvocationHandler 接口中的 invoke 方法,当需要动态代理时只需要根据接口和一个实现了 InvocationHandler 的代理对象 A 生成一个最终的自动生成的代理对象 A_。这样最终的代理对象 A_无论调用什么方法,都会执行 InvocationHandler 的代理对象 A 的 invoke 函数,你就可以在这个 invoke 函数中实现真正的代理逻辑。


Retrofit 中的动态代理


Retrofit 中使用了动态代理是不错,但是并不是为了真正的代理才使用的,它只是为了动态代理一个非常重要的功能,就是“拦截”功能。我们知道动态代理中自动生成的 A_对象的所有方法执行都会调用实际代理类 A 中的 invoke 方法,再由我们在 invoke 中实现真正代理的逻辑,实际上也就是 A_的所有方法都被 A 对象给拦截了。 而 Retrofit 的功能就是将代理变成像方法调用那么简单。


Retrofit 作用


Retrofit 实际上是为了更方便的使用 Okhttp,因为 Okhttp 的使用就是构建一个 Call,而构建 Call 的大部分过程都是相似的,而 Retrofit 正是利用了代理机制带我们动态的创建 Call,而 Call 的创建信息就来自于你的注解。


3.OkHttp


请求任务队列


Okhttp 使用了一个线程池来进行异步网络任务的真正执行,而对于任务的管理采用了任务队列的模型来对任务执行进行相应的管理,有点类似服务器的反向代理模型。Okhttp 使用分发器 Dispatcher 来维护一个正在运行任务队列和一个等待队列。如果当前并发任务数量小于 64,就放入执行队列中并且放入线程池中执行。而如果当前并发数量大于 64 就放入等待队列中,在每次有任务执行完成之后就在 finally 块中调用分发器的 finish 函数,在等待队列中查看是否有空余任务,如果有就进行入队执行。Okhttp 就是使用任务队列的模型来进行任务的执行和调度的。


复用连接池


Http 使用的 TCP 连接有长连接和短连接之分,对于访问某个服务器的频繁通信,使用短连接势必会造成在建立连接上大量的时间消耗;而长连接的长时间无用保持又会造成资源你的浪费。Okhttp 底层是采用 Socket 建立流连接,而连接如


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


果不手动 close 掉,就会造成内存泄漏,那我们使用 Okhttp 时也没有做 close 操作,其实是 Okhttp 自己来进行连接池的维护的。在 Okhttp 中,它使用类似引用计数的方式来进行连接的管理,这里的计数对象是 StreamAllocation,它被反复执行 aquire 与 release 操作,这两个函数其实是在改变 Connection 中的List<WeakReference<StreamAllocation>>大小。List 中 Allocation 的数量也就是物理 socket 被引用的计数(Refference Count),如果计数为 0 的话,说明此连接没有被使用,是空闲的,需要通过淘汰算法实现回收。


4. RxJava


从 15 年开始,前端掀起了一股异步编程的热潮,在移动 Android 编程过程中,经常会听到观察者与被观察者等概念。


观察者与被观察者通信


Observable 的通过 create 函数创建一个观察者对象。


public final static <T> Observable<T> create(OnSubscribe<T> f) {


return new Observable<T>(hook.onCreate(f));


}


Observable 的构造函数如下:


protected Observable(OnSubscribe<T> f) {


this.onSubscribe = f;


}


创建了一个 Observable 我们记为 Observable1,保存了传入的 OnSubscribe 对象为 onSubscribe,这个很重要,后面会说到。


onSubscribe 方法


public final Subscription subscribe(Subscriber<? super T> subscriber) {


return Observable.subscribe(subscriber, this);


}


private static <T> Subscription subscribe(Subscriber<? super T> subscriber, Observable<T> observable) {


...


subscriber.onStart();


onSubscribe.call(subscriber);


return hook.onSubscribeReturn(subscriber);


}


线程切换过程(Scheduler)


RxJava 最好用的特点就是提供了方便的线程切换,但它的原理归根结底还是 lift,使用 subscribeOn()的原理就是创建一个新的 Observable,把它的 call 过程开始的执行投递到需要的线程中;而 observeOn() 则是把线程切换的逻辑放在自己创建的 Subscriber 中来执行。把对于最终的 Subscriber1 的执行过程投递到需要的线程中来进行。

Android 进阶之路

对我们开发者来说,一定要打好基础,随时准备战斗。不论寒冬是否到来,都要把自己的技术做精做深。虽然目前移动端的招聘量确实变少了,但中高端的职位还是很多的,这说明行业只是变得成熟规范起来了。竞争越激烈,产品质量与留存就变得更加重要,我们进入了技术赋能业务的时代。


**技术之路就是漫长的打怪升级,不断学习前人的踩坑经验才能提升自己,切忌闭门造车!**所谓独乐乐不如众乐乐,在我当时确立好 Android 方向时,就已经开始梳理自己的成长路线了,包括技术要怎么系统地去学习,都列得非常详细,免费分享给大家。


从架构基础开始,分了 8 个模块来逐步从基础进阶到架构师的环节:


架构师筑基语言基础


目前 Android APP 开发主流语言就是 Java 语言,Java 语言最大的特性就是提高了软件的交互可能性,可以说安卓手机几乎所有应用程序都是利用 Java 语言来进行编写的。



设计思想解读开源框架


随着互联网企业的不断发展,产品项目中的模块越来越多,用户体验要求也越来越高,想实现小步快跑、快速迭代的目的越来越难,插件化技术应用而生。如果没有插件化技术,美团、淘宝这些集成了大量“app”的应用,可能会有几个 g 那么大。


所以,当今的 Android 移动开发,不会热修复、插件化、组件化,80%以上的面试都过不了。



360°全方位性能调优


在不同层次的开发工程师手里,因为技术水平的参差不齐,即使很多手机在跑分软件性能非常高,打开应用依然存在卡顿现象。


另外,随着产品内容迭代,功能越来越复杂,UI 页面也越来越丰富,也成为流畅运行的一种阻碍。综上所述,对 APP 进行性能优化已成为开发者该有的一种综合素质,也是开发者能够完成高质量应用程序作品的保证。



Android 框架体系架构


Android 开发者也往往因为网上 Copy 代码习惯了而导致对这块经常“使用”的代码熟悉而又陌生:熟悉的是几乎天天在和它们打交道, 天天在复制这些代码 ;陌生的是虽然天天和这些代码打交道,但是并没有深入研究过这些代码的原理,代码深处的内涵。



用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
“我是培训 + 外包出来的(1),flutter与android混合开发