美文网首页Android开发程序人生码农的世界
Android面试指南(蚂蚁金服)

Android面试指南(蚂蚁金服)

作者: 为自己代颜_ | 来源:发表于2018-04-26 20:17 被阅读348次

    蚂蚁金服第一轮电话面试主要针对项目中的难点知识点

    (一)kotlin有哪些优点 源码是怎么实现的

    Kotlin是JetBrains推出项目,是一种在Java虚拟机上运行的静态类型编程语言,也可以被编译成为JavaScript源代码。2016年2月15日,官方发布了第一个稳定的release版本,官方扶正Kotlin的举动火遍整个Android开发圈。

    kotlin特点及优点:

    1)Kotlin与Java语法并不兼容,但可以和Java代码相互运作(混合编译)。

    2)代码精简,相同的功能,比Java实现的代码量少。

    举例:2.1如你要创建一个Entity类,除了声明属性外你还要创建对应的get、set方法,分别来看看Java和Kotlin是怎么做,Kotlin代码就一行搞定,而且modelBean用data关键字来修饰增加copy属性;

    3)代码语句不需要作为结束,这点和Python一致。(加了分号也不会报错);

    4)使用var声明变量,用val声明常量,用fun声明函数。

    5)继承父类和接口无需extends、implements,只需:

    6)空指针检测。NullPointerException(也称NPE)是开发过程中最常遇到的Exception之一了,为此我们不得不写很多防御性代码去判断一个对象是否为null。而Kotlin默认是不需要变量为null的,否则在编译的时候就会报错,Kotlin里面可以没有空指针问题,在Android中使用Java就会存在很多令人头大的空指针问题。

    7)数据类型自动推断,创建对象无需new。

    8) 减少findById的获取,直接使用控件的id来操作

    9) 支持扩展函数,可以对指定类进行扩展,通过扩展的特殊声明来实现。

    10) 支持lambda表达式

    11) object 修饰class 直接支持单例模式操作

    12)无需增加额外库,就给你提供了支持函数式

    ```

    fun main(args: Array) {

      val nameList =listOf("Kotlin", "Java", "Python","JavaScript", "Scala", "C", "C++","Go", "Swift")

        nameList.filter {

            it.startsWith("K")

        }.map {

            "$it is a very good language"

        }.forEach {

        println(it)

        }

    }

    ```

    结果kotlin is a very goodlanguage

    balabala.....

    (二)kotlin源码是怎么实现的

    1.kotlin底层是基于Java虚拟机(JVM)编程,这意味着Kotlin可以写服务器代码;

    2.基于Android和Browser编程,这意味着不仅可以写客户端编程,连前端开发都可以;

    3.基于Native编程,直接绕过JVM与底层代码打交道,好彪悍;

    (三)kotlin扩展方法是类封装吗 类A继承类B中的扩展方法 需要注意啥

    扩展方法的原理:Kotlin中类的扩展方法并不是在原类的内部进行拓展,通过反编译为Java代码,可以发现,其原理是使用装饰模式,对源类实例的操作和包装,其实际相当于我们在Java中定义的工具类方法,并且该工具类方法是使用调用者为第一个参数的,然后在工具方法中操作该调用者;该调用者在Kotlin中使用this关键字表示;比如:定义一个String的扩展方法,其中的this表示调用者本身;

    扩展属性的原理:类的扩展属性原理其实与扩展方法是一样的,只是定义的形式不同,扩展属性必须定义get和set方法,并且类似于接口中定义的变量,由于扩展属性实际上不会向类添加新的成员, 因此无法让一个扩展属性拥有一个 后端域变量。 所以, 对于扩展属性不允许存在初始化器. 扩展属性的行为只能通过明确给定的取值方法与设值方法来定义。val Foo.bar = 1 // 错误: 扩展属性不允许存在初始化器(一般的类属性,在其对象实例中都会分配一点内存来存储属性的值。)

    扩展函数与扩展属性的神奇之处在于,可以在不修改原来类的条件下(并非原类内部扩展的类的实例并不是源类),使用函数和属性,表现得就像是属于这个类的一样。扩展属性,扩展函数的本质是以静态导入的方式来实现的。

    类中存在与成员函数同名的扩展函数,用方法名来调用的是成员函数;

    当类存在以重载方式实现的同名扩展函数,用方法名来调用的是扩展函数

    要声明一个扩展函数, 我们需要在函数名之前添加前缀, 表示这个函数的 接收者类型(receiver type), 表明我们希望扩展的对象类型

    代码展示及解析请参考:[Kotlin的扩展属性和扩展方法]

    (四)kotlin lamda表达式源码解析

    Lambda 表达式,其实就是匿名函数。而函数其实就是功能(function),匿名函数,就是匿名的功能代码,其实所有的 Lambda 表达式都是 Function 的实现。我们先来看一个 Lambda 表达式的例子:

    ```funmain(args:Array){

        vallambda={

        left:Int,right:Int->left+right}

        println(lambda(2,3))

    }```

    大家可以看到我们定义了一个变量 lambda,赋值为一个 Lambda 表达式。Lambda表达式用一对大括号括起来,后面先依次写下参数及其类型,如果没有就不写,接着写下 ->,这表明后面的是函数体了,函数体的最后一句的表达式结果就是 Lambda 表达式的返回值,比如这里的返回值就是参数求和的结果。后面我们用 () 的形式调用这个 Lambda 表达式,其实这个 () 对应的是 invoke 方法,换句话说,我们在这里也可以这么写:println(lambda.invoke(2,3))

    这两种调用的写法是完全等价的。毫无疑问,这段代码的输出应该是 5。

    详细博文请参考:细说 Lambda 表达式

    (五)安卓的启动过程以及android中进程是如何创建的

    1.Android的五层架构从上到下依次是:应用层,应用框架层,库层,运行时层,Linux内核层。

    2.而在Linux中,它的启动可以归为一下几个流程:

    Boot Loader——>初始化内核——>。。。。。。

    3.当初始化内核之后,就会启动一个相当重要的祖先进程,也就是init进程,在Linux中所有的进程都是由init进程直接或间接fork出来的。

    4.而对于Android来说,前面的流程都是一样的,而当init进程创建之后,会fork出一个Zygote(['zaɪgəʊt])进程,这个进程是所有Java进程的父进程。我们知道,Linux是基于C的,而Android是基于Java的(当然底层也是C)。所以这里就会fork出一个Zygote Java进程用来fork出其他的进程。

    5.当Zygote被初始化的时候,会fork出System Server进程,这个进程在整个的Android进程中是非常重要的一个,地位和Zygote等同,它是属于Application Framework层的,Android中的所有服务,例如AMS, WindowsManager, PackageManagerService等等都是由这个SystemServer fork出来的。所以它的地位可见一斑。而当System Server进程开启的时候,就会初始化AMS,同时,会加载本地系统的服务库,创建系统上下文,创建ActivityThread及开启各种服务等等。而在这之后,就会开启系统的Launcher程序,完成系统界面的加载与显示。

    详细过程请参考Android从启动到程序运行整个过程的整理

    (六)android中app的启动过程

    首先交代下整个流程分析的场景:用户点击Launcher上的应用图标到该应用主界面启动展示在用户眼前。这整个过程涉及到跨进程通信。 Launcher响应用户点击,通知AMS;此时AMS响应处理Launcher发来的请求;AMS创建新的进程(将要打开的应用进程)并启动ActivityThread(应用的UI线程);ActivityThread通过Binder将ApplicationThread类型的Binder对象传递给ActivityManagerService,方便ActivityManagerService后续与其的通信;准备工作完成后,ActivityManagerService通知ActivityThread启动Activity; ActivityThread调度执行Activity的生命周期方法,完成启动Activity的工作

    详细步骤解析请参考博文:Android Application启动流程分析

    (七)http和https的区别 https用的什么协议   https加密算法  讲一下摘要认证

        ##Https的工作原理

        HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。HTTPS一般使用的加密与HASH算法如下:

    非对称加密算法:RSA,DSA/DSS;对称加密算法:AES,RC4,3DES;HASH算法:MD5,SHA1,SHA256 (HTTPS的中那些加密算法)摘要认证请查看链接中的数字签名部分

    通过写信,邮信的方式更加形象直观(公钥、私钥、数字证书_解释

      ##HTTPS和HTTP的区别主要如下:

      1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

      2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。

      3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

      4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

    (八)retrofit 拦截器和okHttp有什么联系

    随着Google对HttpClient 摒弃,和Volley的逐渐没落,OkHttp开始异军突起,而Retrofit则对okHttp进行了强制依赖。Retrofit是由Square公司出品的针对于Android和Java的类型安全的Http客户端,如果看源码会发现其实质上就是对okHttp的封装,使用面向接口的方式进行网络请求,利用动态生成的代理类封装了网络接口请求的底层,retrofit相对于其它网络框架使用上更加简洁明了,并且配置灵活,能达到解耦的效果。Retrofit利用注解来方便拼装请求参数(比如headers或者params,就是通过注解,然后拼接到网络请求中),对于返回结果也可以完美适配Rxjava,如果用的其他结构的数据,也可以自己写相对应的Covers来解析。总而言之,Retrofit是基于okhttp的封装,更加方便利用okhttp的使用。缓存机制都是用的okHttp的功能

    okhttp其实和 httpurlconnection是一个级别的。OkHttp和HttpUrlConnection以及Volley的区别

    具体使用步骤:Retrofit2使用(非常简洁易懂)

    (九)volley现在为什么不流行了

    volley重点在于request的队列的管理,其他的地方都很不强,一般都是volley+okhttp接合使用,不过如果没有特别多的网络性能要求(一般而言,比如你们用户量没有超百万)还是默认使用volley那套网络连接方式就够了。OkHttp引擎在Android 4.4上是基于HttpURLConnection的。 Twitter, Facebook 和 Snapch都采用了它。Volley的工作方式是创建不同的request,然后把它们添加到队列中(queue)。一个项目只需要一个queue就足够了,每次你想创建一个request的时候你都只需要获得这个唯一的queue来添加。Volley可以轻松设置OkHttp作为其传输层,Request参数中设置HttpStack。volley 只是适合小数据的传输,上传文件下载文件这些都支持的不是很好

    Volley/Gson的解决方案比较成熟,因为这是谷歌的解决方案,同时也因为出现在安卓开发者网站上,因此在2013到2014年都非常流行。到目前为止,这仍然是一个很好的选择,它是简单有效的。不过需要考虑一下的是Volley和Gson现在不怎么更新了。

    okhttp还比volley有更多的选择。文中说的组合是说替换volley的HttpStack为okhttp的stack。并不是说okhttp只做了传输层的封装……volley的网络请求过程还就直接封装成异步的了……

    拓展性高的是okhttp,数据流还是用okio来优化的,请求过程有同步,也有异步方法,响应体保持同步阻塞,大大的方便了有进行连续多次网络请求的需求。

    (十)还有rxjava好处

    1.错误处理:只要有异常发生,onError()一定被调用,这极大简化了错误处理。只要在一个地方处理错误即可。操作符调用链中一旦有一个抛出了异常,就会直接执行onError方法。

    2.调度器:

    假设你编写的Android app需要从网络请求数据(感觉这是必备的了,还有单机?)。网络请求需要花费较长的时间,因此你打算在另外一个线程中加载数据,那么问题来了!编写多线程的Android应用程序是很难的,因为你必须确保代码在正确的线程中运行,否则的话,可能导致app崩溃,最常见的就是在非主线更新UI。使用RxJava,你可以使用subscribeOn()指定观察者代码运行的线程,使用observerOn()指定订阅者运行的线程:

    ```

    .subscribeOn(Schedulers.io())

    .observeOn(AndroidSchedulers.mainThread())

    .subscribe(bitmap - > myImageView.setImageBitmap(bitmap));

    ```

    3.订阅(Subscriptions)绑定生命周期防止内存泄露

    详细可参考博文:RxJava之响应式编程的好处

    (十一)项目中使用了哪些类库 

    不用具体类库的名字,大体说下比如网络请求,图片处理,下拉刷新,内存检测等等就可以~~~

    (十二)长链接和短链接

      短连接:接是指SOCKET连接后,发送接收完数据后马上断开连接。

      长连接:连接->传输数据->保持连接 -> 传输数据-> ...........->直到一方关闭连接,多是客户端关闭连接。

    长连接指建立SOCKET连接后不管是否使用都保持连接,但安全性较差。

    什么时候用长连接,短连接?

    长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况,。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,次处理时直接发送数据包就OK了,不用建立TCP连接。例如:数据库的连接用长连接, 如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。

    而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。

    总之,长连接和短连接的选择要视情况而定。

    (十三)项目中负责哪些部分

    RN开发,小程序开发,最新版本App这种涉及到的部分

    相关文章

      网友评论

        本文标题:Android面试指南(蚂蚁金服)

        本文链接:https://www.haomeiwen.com/subject/tjnmlftx.html