Android------面试简答题

一。.简单概述SVN与Git的区别?

1.GIT是分布式的,SVN不是

2.GIT把内容按元数据方式存储,而SVN是按文件

3.GIT分支和SVN的分支不同

4.GIT没有一个全局的版本号,而SVN有

5.GIT的内容完整性要优于SVN

二.简述listview的优化策略?

1.对convertView进行判空,为空时加载新布局,不为空时复用。

2.定义ViewHolder,减少findViewByid的次数

3.加载数据过多时采用分页加载和图片异步加载。


三.Intent可以传递哪些数据类型?

1.简单或基本的数据类型

2.传递一个Bundle

3.传递serializable对象

4.Intent

四.事件冲突的解决

解决ScrollView(垂直滚动的一个布局)嵌套ListView问题?

1、手动设置ListView高度

2.使用单个ListView取代ScrollView中所有内容

3.使用LinearLayout取代ListView

4.自定义可适应ScrollView的ListView


  解决ListView嵌套ViewPager时,滑动事件冲突?

    点击打开链接

因为ViewPager是放在ListView上面的,所以当我们点击ViewPager时,这个事件就被最上层的ViewPager给拦截了,ListView获取不到这个事件,所以我们就要根据不同的情况来传递给ListView和ViewPager这个触摸事件.

 我们需要判断这个滑动事件是传递给ViewPager来执行还是ListView来执行,

这里不得不提到一个方法:getParent().requestDisallowInterceptTouchEvent(boolean disallowIntercept);,这个方法是判断事件是由父view处理还是子view来处理;

我们重写一个类来继承ViewPager,重写public boolean dispatchTouchEvent(MotionEvent ev) 这个方法,这个方法是用来进行事件的分发;在这个方法中来判断手指的动作,我们记录手指放下的位置,当手指移动时,我们判断手指滑动的距离,当在x轴上的滑动距离大于y轴上的滑动距离时,这个时候应该滑动事件就应该传递给ViewPager来处理,这个时候调用:getParent().requestDisallowInterceptTouchEvent(boolean disallowIntercept);这个方法,参数设置为true,这就是ViewPager自行处理滑动事件,而不是传递给ListView来处理滑动事件,当在y轴上的滑动距离大于x轴上的滑动距离时,这个时候,再次调用getParent().requestDisallowInterceptTouchEvent(boolean disallowIntercept);这个时候我们把参数设置为false,这样滑动事件就由ListView来处理,而不是传递给ViewPager处理.

简单理解就是(利用事件分发机制,在方法中记住手指放下的位置,记录手指在X轴和Y轴的滑动距离,当X轴滑动的距离大于Y轴滑动距离的时候,事件传递给ViewPager来处理,把上面方法的参数设置为True,同理Y轴距离大于X轴距离,事件传递给ListView,将参数设置为false)。

五.自定义控件的实现思路:

很多时候会遇到系统框架中提供的控件无法满足我们产品的设计需求,这时候需要使用自定义view。

View绘制分为三个过程:

OnMeasure(测量,算出自己需要占用多大的面积);

OnLayout(设置宽高);

OnDraw(在canvas 画布上画出我们需要的View样式);

1.需要自定义一个类继承该控件,比如继承View;

2.重写里面的构造方法;

3.重写view的onDraw方法,绘制控件的样式,这里你使用canvas来绘制,你布局中使用这个控件就是你绘制的样子

4.在XML中引入该类就可以了。


六.简述Android中的事件分发机制:

 dispatchTouchEvent(事件分发) onInterceptTouchEvent(事件拦截) onTouchEvent(事件响应)

Touch事件发生时,会触发 dispatchTouchEvent,如果返回True,表示事件被消费,如果返回False,会传递给onInterceptTouchEvent,在事件拦截事件中,如果返回True,表示事件被消费,如果返回False,会传递给onTouchEvent,在事件响应中,如果返回True,表示事件被消费,如果返回False,那么这个事件会从当前View向上传递,并且都是由上层View的onTouchEvent来接收,如果传递到上面的onTouchEvent也返回False则接着向上传递,直到最上层如果还是返回False,则该事件会消失。

七.简述Activity的四种启动模式:

(standard            singleTop           singleTask         singleInstance)

standard

默认模式,可以不用写配置。在这个模式下,都会默认创建一个新的实例。因此,在这种模式下,可以有多个相同的实例,也允许多个相同Activity叠加。

singleTop

(正常情况下突然出现的聊天界面)

栈顶复用模式,可以有多个实例,但是不允许多个相同Activity叠加。即,如果Activity在栈顶的时候,启动相同的Activity,不会创建新的实例,而会调用其onNewIntent方法。

singleTask

(浏览器 ,主-a-b-c)

栈内复用模式,是一种单实例模式,只有一个实例。在同一个应用程序中启动他的时候,若Activity不存在,则会在当前task创建一个新的实例,若存在,则会把task中在其之上的其它Activity destory掉并调用它的onNewIntent方法。

如果是在别的应用程序中启动它,则会新建一个task,并在该task中启动这个Activity,singleTask允许别的Activity与其在一个task中共存,也就是说,如果我在这个singleTask的实例中再打开新的Activity,这个新的Activity还是会在singleTask的实例的task中。(例如:
若我的应用程序中有三个Activity,C1,C2,C3,三个Activity可互相启动,其中C2为singleTask模式,那么,无论我在这个程序中如何点击启动,如:C1->C2->C3->C2->C3->C1-C2,C1,C3可能存在多个实例,但是C2只会存在一个,并且这三个Activity都在同一个task里面。)

singleInstance

(闹钟(弹出),支付宝支付界面)

单实例模式,这是一种加强的singletask模式,除了具有singletask特性外还加强了一点那就是只能单独的位于一个任务栈中,

只有一个实例,并且这个实例独立运行在一个task中这个task只有这个实例,不允许有别的Activity存在。

八.简述屏幕适配的方案:

分为 屏幕尺寸匹配屏幕密度匹配

屏幕尺寸匹配分为布局匹配(建议使用相对布局,禁用绝对布局),布局组件匹配(使用权重,自适应,充满来控制视图组件的宽度和高度),图片资源匹配(自动拉伸位图)和用户界面流程匹配。

屏幕密度匹配分为布局控件匹配,图片资源匹配。

九.图文混排的实现思路:

通过ImageSpan来放置图片,再创建一个SpannableString对象,以便插入用ImageSpan对象封装的图像,最后用ImageSpan对象替换你指定的字符串,完成EditText的图文混排

在 TextView 中显示图片,可以使用Html.fromHtml(source, imageGetter, tagHandler)通过自定义imageGetter来异步加载图片,最后完成图文混排。

十.简述对OkHttp框架的认识:

一个处理网络请求的开源项目,是安卓端最火热的轻量级框架.替代HttpUrlConnection和Apache HttpClient

优势:

1.允许连接到同一主机地址的所有请求,提高请求效率。

2.共享Socket,减少对服务器的请求次数。

3.通过连接池,减少了请求延迟。

4.缓存响应数据,减少重复的网络请求。

5.减少了对数据流量的消耗。

6.自动处理GZip压缩。


功能:

1.get  post请求;

2.文件的上传下载。

3.加载图片

4.支持请求回调,直接返回对象,对象集合;

5.支持session的保持。

十一.支付宝的支付流程:

Android------面试简答题_第1张图片


十二.图片加载框架的几种区别:

主要对比 (Imageloader,Picasso,Glide,Fresco

<< Universal ImageLoader 是很早开源的图片缓存,在早期被很多应用使用

  1. ImageLoader实现Bitmap三级缓存: 内存——磁盘——网络
    ImageLoader 收到加载及显示图片的任务,并将它交给 ImageLoaderEngine,ImageLoaderEngine 分发任务到具体线程池去执行,任务通过 Cache 及 ImageDownloader 获取图片,中间可能经过 BitmapProcessor 和 ImageDecoder 处理,最终转换为Bitmap 交给 BitmapDisplayer 在 ImageAware 中显示。
    ①支持下载进度监听
    ②可以在 View 滚动中暂停图片加载:
    可以通过 PauseOnScrollListener 接口可以在 View 滚动中暂停图片加载。
    ③默认实现多种内存缓存算法:ImageLoader 默认实现了较多缓存算法,如 Size 最大先删除、使用最少先删除、最近最少使用、先进先删除、时间最长先删除等。

  >> picasso是Square公司开源的一个Android图形缓存库,可以实现图片下载和缓存功能

    Picasso不仅实现了图片异步加载的功能,还解决了android中加载图片时需要解决的一些常见问题:

自带内存和硬盘二级缓存功能

①自带统计监控功能:支持图片缓存使用的监控,包括缓存命中率、已使用内存大小、节省的流量等。

②没有本地缓存:但是配合okhhtp的缓存使用

  Glide是一个高效、开源、 Android设备上的媒体管理框架,Glide具有获取、解码和展示视频剧照、图片、动画等功能,它还有灵活的API,这些API使开发者能够将Glide应用在几乎任何网络协议栈里。创建Glide的主要目的有两个,一个是实现平滑的图片列表滚动效果(滚动流畅),另一个是支持远程图片的获取、大小调整和展示

   >>特点

①图片缓存->媒体缓存
Glide 不仅是一个图片缓存,它支持 Gif、WebP、缩略图。甚至是 Video,所以更该当做一个媒体缓存。

十三.Android各版本的区别?

android 5.0与之前相比有什么区别?

1.多核处理器的优化
2.运行速度比3.1提高1.8倍;

android 6.0与之前相比有什么区别?
1.原生的应用权限管理;(无需第三方应用和Root权限,用户可以在安
装应用时选择关闭一些应用权限。)
2.指纹识别
3.流量保护模式
4.锁屏下语音搜索

5.菜单键快速应用切换(双击菜单键,就能自动切换到上一个应用


十四.简述利用HTTPS进行加密的流程:

Android------面试简答题_第2张图片

注意,为了更好的区分明文和密文,用【AA】代表AA被加密,AA 代表正常未加密

1.client 发出请求

2.server 收到请求,并自己生成一对密钥,即 公钥S 和 私钥S

3.server 把生成的 公钥S 传递给 client (除了 公钥S ,还有很多额外信息)

4.client 收到 公钥S后进行判断,若无效,弹出警告,否则生成一串随机数,我们称之为 私钥C ,然后 client 用 server 传过来的 公钥S 对该随机数加密,形成【私钥C】

5.client 把【私钥C】传递给 server

6.server 收到【私钥C】,用 私钥S 把【私钥C】解密成私钥C,然后把需要传递的数据用 私钥C 进行加密

7.server 把【数据】传递给 clien

8.client 收到【数据】,用 私钥C 解密,完成一波收割

(用HTTPS进行加密的优点:利用非对称加密的安全性来加密那一串随机数--私钥C;利用对称加密的快捷性来加密报文,总体来说就是把真正加密解密的密钥(私钥C)用公钥S和私钥S来加密)

注:对称加密:是指加密和解密用一致的密钥,特点是快!!!

非对称加密:指密钥区分公钥和私钥,公钥加密,私钥解密(私钥好比唯一一把钥匙,公钥好比锁,钥匙只有一把,但锁可以有很多,被锁头锁上的数据全天下只有一把私钥才能打开),特点是安全,但是慢!!!

十五.单例模式的优缺点:

优点:

  1. 提供了对唯一实例的受控访问

  2. 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象单例模式无疑可以提高系统的性能。

  3. 允许可变数目的实例

缺点:

  1. 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。

  2. 单例类的职责过重,在一定程度上违背了”单一职责原则”。

  3. 滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失

单例模式例子:

Public class A{

Private static A  instance=null;

public synchronized static A GetInstance(){

if(instance==null){

instance=new A();

}

return instance;

}

}

十六.TCP和UDP的区别?

TCP是面向连接的协议,也就是说在收发数据前,必须和对方建立可靠的连接,一个TCP连接必须经过三次握手才能建立起来。

UDP是一个非连接的协议,传输数据之前源端和终端不建立连接

区别:TCP和UDP都是网络传输协议,所有基于网络访问的过程都可能涉及这两个协议。TCP是可靠连接,即传输的数据必须完整,UDP是不可靠连接,即传输过程不保证数据的完整性,如语音聊天时,当网络条件不好情况下,可能会丢失内容。

http协议:应用层协议,并且http协议是基于tcp连接的,主要解决的是如何包装协议的

tcp协议:传输层协议,通常也叫做tcp/ip协议,主要解决数据如何在网络中传输

udp协议:传输层协议,用户数据报协议,不可靠的协议,只负责把应用层的协议的数据传送到ip层的数据报,而不管数据是否到达。

ip协议:网络层。

socket连接:长连接(是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元,说白了socket就是一组调用接口(API),封装了做tcp/ip开发的网络接口,通过Socket,我们才能使用TCP/IP协议。)

http连接:短连接

TCP/IP协议和Http协议之间的关系

TPC/IP协议是传输层协议,主要解决数据 如何在网络中传输,而HTTP是应用层协议,主要解决如何包装数据,而socket则是对TCP/IP协议的封装和应用(程序员层面上)。实际上http协议就是建立在tcp/ip协议之上的。

tcp/ip协议, http协议,socket三者之间的关系

实际上,传输层的TCP是基于网络层的IP协议的,而应用层的HTTP协议又是基于传输层的TCP协议的,而Socket本身不算是协议,它只是提供了一个针对TCP或者UDP编程的接口。


十七.内存泄露产生的原因及解决方法?

原因:持有对象的强引用,且没有及时释放,进而造成内存单元一直被占用,浪费空间,甚至可能造成内存溢出!

解决办法:  数据库的cursor没有关闭 (及时关闭)

                     对Adapter进行优化

                     加载图片时,Bitmap对象不使用recycle()释放内存

                     静态变量引起内存泄露

                     使用Application的Context

                     UI界面优化


十八.MVP与MVC的区别?

MVC:

MVC全称是Model - View - Controller,是模型(model)-视图(view)-控制器(controller)的缩写。MVC是一种框架模式而非设计模式,使用 MVC,把业务逻辑抽离到 Controller 中,让 View 层专注于显示 UI。

优点: (1)首先就是理解比较容易,技术含量不高,这对开发和维护来说成本较低也易于维护与修改。

(2)耦合性不高,表现层与业务层分离各司其职,对开发来说很有利。

缺点:模型和视图要严格的分离,这样也给调试应用程序带来了一定的困难。每个构件在使用之前都需要经过彻底的测试。

MVP

MVP模式是MVC模式的一个演化版本,MVP全称Model-View-Presenter。目前MVP在Android应用开发中越来越重要了。

优点: (1)MVP模式会解除View与Model的耦合,有效的降低View的复杂性。同时又带来了良好的可扩展性、可测试性,保证系统的整洁性和灵活性。

(2)MVP模式可以分离显示层与逻辑层,它们之间通过接口进行通信,降低耦合。

区别

MVP中View不能直接访问Model,需要通过Presenter发出请求,View与Model不能直接通信。

十九.启动服务的两种方式,及区别?

 startservice 和bindservice

区别:

1. 使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行

2. 使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。

二十.Android 四大组件

1.Activity

1)一个Activity通常就是一个单独的屏幕(窗口);

2)Activity之间通过Intent进行通信;

3)Android每一个应用中的Activity都必须在AndroidManifest.xm配置文件中声明,否则系统将不识别也不执行该Activity.


2.Service(服务)

1)Service用于在后台完成用户指定的操作,Service分为两种:

astarted(启动):当应用程序组件(如activity)调用startService()方法启动服务时,服务处于started状态。

bbound(绑定):当应用程序组件调用bindService()方法绑定到服务时,服务处于bound状态。

Service生命周期?

1.StartService

 Oncreate

OnstartCommand

Ondestroy

2.BindService

Oncreate

OnBind

OnUnbind

OnDestroy
startService()bindService()区别:

当服务是started状态时,其生命周期与启动它的组件无关,并且可以在后台无限期运行,即使启动服务的组件已经被销毁,服务仍然运行。

使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止;

Service完整的生命周期从调用onCreate()开始直到调用onDestroy()结束。

Service有两种使用方法:

1)以调用Context.startService()启动,而以调用Context.stopService()结束。

2)以调用Context.bindService()方法建立,以调用Context.unbindService()关闭。


Service通常位于后台运行,它一般不需要与用户交互,因此Service组件没有图形用户界面。Service组件需要继承Service基类。Service组件通常用于为其他组件提供后台服务或监控其他组件的运行状态。

3.Content Provider(内容提供者)

1)各应用程序之间可以通过ContentResolver类从该内容提供者中获取或存入数据

2)只有需要在多个应用程序间共享数据是才需要内容提供者。

3)ContentProvider实现数据共享

4)开发人员不会直接使用ContentProvider类的对象,大多数是通过ContentResolver对象实现对ContentProvider的操作。


4.Broadcast Receiver(广播接收者)

定义:

Broadcast是四大组件之一,是一种广泛运用在应用程序之间传输信息的机制,通过发送Intent来传送我们的数据

Broadcast Receiver的使用场景:

同一App具有多个进程的不同组件之间的消息通信

不同App之间的组件之间的消息通信

    Broadcast Receiver实现机制

  • 自定义广播类继承BroadcastReceiver,复写onReceiver()

  • 通过Binder机制向AMS进行注册广播

  • 广播发送者通过Binder机制向AMS发送广播

  • AMS查找符合相应条件的广播发送到BroadcastReceiver相应的循环队列中

  • 消息队列执行拿到广播,回调BroadcastReceiver的onReceiver()

LocalBroadcastManager特点

  • 本地广播只能在自身App内传播,不必担心泄漏隐私数据

  • 本地广播不允许其他App对你的App发送该广播,不必担心安全漏洞被利用

  • 本地广播比全局广播更高效

  • 以上三点都是源于其内部是用Handler实现的


  • 1)你的应用可以使用它对外部事件进行过滤,只对感兴趣的外部事件(如当电话呼入时,或者数据网络可用时)进行接收并做出响应。广播接收器没有用户界面。然而,它们可以启动一个activityserice来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力,例如闪动背灯、震动、播放声音等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。

2)广播接收者的注册有两种方法,分别是程序动态注册和AndroidManifest文件中进行静态注册。

3)动态注册广播接收器特点是当用来注册的Activity关掉后,广播也就失效了。静态注册无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器也是打开着的。也就是说哪怕app本身未启动,该app订阅的广播在触发时也会对它起作用。

总结

1)4大组件的注册

4大基本组件都需要注册才能使用,每个ActivityserviceContent Provider都需要在AndroidManifest文件中进行配置。AndroidManifest文件中未进行声明的activity、服务以及内容提供者将不为系统所见,从而也就不可用。而broadcast receiver广播接收者的注册分静态注册(在AndroidManifest文件中进行配置)和通过代码动态创建并以调用Context.registerReceiver()的方式注册至系统。需要注意的是在AndroidManifest文件中进行配置的广播接收者会随系统的启动而一直处于活跃状态,只要接收到感兴趣的广播就会触发(即使程序未运行)。

2)4大组件的激活

内容提供者的激活:当接收到ContentResolver发出的请求后,内容提供者被激活。而其它三种组件activity、服务和广播接收器被一种叫做intent的异步消息所激活

3)4大组件的关闭

内容提供者仅在响应ContentResolver提出请求的时候激活。而一个广播接收器仅在响应广播信息的时候激活。所以,没有必要去显式的关闭这些组件。Activity关闭:可以通过调用它的finish()方法来关闭一个activity。服务关闭:对于通过startService()方法启动的服务要调用Context.stopService()方法关闭服务,使用bindService()方法启动的服务要调用Contex.unbindService()方法关闭服务。

二十一.简述实现图片上传的过程?

图片的上传可以分为拍照上传和选择系统相册图片上传;

具体步骤为:1.选择跳转到系统相册或者在startactivityforresult方法调用系统的摄像头,随便拍张照片,把照片保存在某一目录下面;

2.点击完成后,会在onactivityresult中,根据目录的地址,再把这目录下面的资源得转换为文件,得到文件的URL;

3.通过这个URL,运用imageload(第三方插件)或者Glide显示图片既可。

二十二.Android与JS之间的交互(WebView的基本使用)?

在页面布局很复杂并且是动态的时候,android本身的控件就变得不是那么地灵活了,只有借助于网页的强大布局能力才能实现,这个时候就用到了Webview。

1.在布局中引入Webview控件;

2.在Activity或者Fragment中调用Loadurl方法,可以加载网址也可以加载本地文件;

3.最后别忘了加上联网的权限。

二十三.Android常用的设计模式?

1.单例模式(确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。)

优点:

  • 对于那些比较耗内存的类,只实例化一次可以大大提高性能,尤其是在移动开发中。

  • 保持程序运行的时候该中始终只有一个实例存在内存中

    代码如下:

                public class A{

           private static  A  instance=null;

       public synchronized  static GetInstance(){

      if(instance==null){

      instance=new A();

}

return instance;

}

}


2.观察者模式(定义对象间的一种一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都能得到通知并被自动更新)

观察者不需要时刻盯着被观察者,而是采用注册(Register)或者称为订阅(Subscribe)的方式,告诉被观察者:我需要你的某某状态,你要在它变化的时候通知我。

Android 开发中一个比较典型的例子是点击监听器 OnClickListener 。对设置 OnClickListener 来说,View 是被观察者,OnClickListener 是观察者,二者通过setOnClickListener() 方法达成订阅关系。订阅之后用户点击按钮的瞬间,Android Framework 就会将点击事件发送给已经注册的OnClickListener 。采取这样被动的观察方式,既省去了反复检索状态的资源消耗,也能够得到最高的反馈速度。

Android的广播机制,EventBus其本质也是观察者模式.

调用registerReceiver方法注册广播,调用unregisterReceiver方法取消注册,之后直接使用sendBroadcast发送广播,发送广播之后,注册的广播会收到对应的广播信息,这就是典型的观察者模式。

观察者模式的三个典型方法它都具有,即注册,取消注册,发送事件.

3.Build模式(建造者模式)

简介:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式的意思就是说将一个对象的各个部分一点一点进行建造(赋值),就像工地上盖房子,哪个部分要什么砖就单独的用一个方法设置这个砖块,不然的话就使用默认的砖块。
示例:AlertDialog.Builder   ImageLoader的初始配置。
AlertDialog dialog = new AlertDialog.Builder(MainActivity.this).setTitle("提示"
.setMessage("确定退出?").create(); 
dialog.show(); 

4.工厂模式
定义:
定义一个用于创建对象的接口,让子类决定实例化哪一个类。
使用场景:

任何需要生成复杂对象的地方,都可以使用工厂方法模式。用new就能创建的对象不需要使用工厂模式,因为使用工厂模式就要增加一个工厂类,增加了系统复杂度。

二十四.简述Rxjava库?

RxJava 在 GitHub 主页上的自我介绍是“一个在Java虚拟机上,使用“可观察的序列”构成基于事件的,异步的程序库”,简单点说,它是一个实现异步操作的库。

优势:

  • 简洁——随着程序逻辑变得越来越复杂,它依然能够保持简洁

  • 高效——快速开发,代码一条从上到下的链式调用,代码结构清晰

观察者模式:

A对象 (观察者)监听B对象 (被观察者)的某种变化,并瞬间做出反应。

当Observable(被观察者)与Observer(观察者)达成订阅关系后,被观察者会调用观察者的OnEvent()方法,将事件传递给观察者。

RxJava的基本概念分别为:Observable(被观察者),Observer(观察者),22subscribe (订阅)、事件; 不同的是,RxJava 把多个事件看做一个队列,并对每个事件单独处理;

二十五.常用算法

1)冒泡排序

冒泡排序,就是从最底那个开始往上比较,遇到比它小的就交换,相当于过五关看六将,不断地向前冲。接着循环第二个...

     Public class A{

    Public static void A (int[] arr){

    int temp;//定义一个临时变量

    for(int i=0;i

   for(int j=1;j

   if(a[j]>a[j+1]){

    temp=a[j];

    a[j]=a[j+1];

    a[j+1]=temp;

  }

 }

 }

 }

 }

2)快速排序

快速排序的原理:选择一个关键值作为基准值。比基准值小的都在左边序列(一般是无序的),比基准值大的都在右边(一般是无序的)。一般选择序列的第一个元素。

一次循环:从后往前比较,用基准值和最后一个值比较,如果比基准值小的交换位置,如果没有继续比较下一个,直到找到第一个比基准值小的值才交换。找到这个值之后,又从前往后开始比较,如果有比基准值大的,交换位置,如果没有继续比较下一个,直到找到第一个比基准值大的值才交换。结束第一次循环,此时,对于基准值来说,左右两边就是有序的了。

接着分别比较左右两边的序列,重复上述的循环。

Android------面试简答题_第3张图片

public class FastSort{

     public static void main(String []args){
        System.out.println("Hello World");
        int[] a = {12,20,5,16,15,1,30,45,23,9};
        int start = 0;
        int end = a.length-1;
        sort(a,start,end);
        for(int i = 0; i){
             System.out.println(a[i]);
         }
        
     }
     
     public void sort(int[] a,int low,int high){
         int start = low;
         int end = high;
         int key = a[low];
         
         
         while(end>start){
             //从后往前比较
             while(end>start&&a[end]>=key)  //如果没有比关键值小的,比较下一个,直到有比关键值小的交换位置,然后又从前往后比较
                 end--;
             if(a[end]<=key){
                 int temp = a[end];
                 a[end] = a[start];
                 a[start] = temp;
             }
             //从前往后比较
             while(end>start&&a[start]<=key)//如果没有比关键值大的,比较下一个,直到有比关键值大的交换位置
                start++;
             if(a[start]>=key){
                 int temp = a[start];
                 a[start] = a[end];
                 a[end] = temp;
             }
         //此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用
         }
         //递归
         if(start>low) sort(a,low,start-1);//左边序列。第一个索引位置到关键值索引-1
         if(end//右边序列。从关键值索引+1到最后一个
     }
     
}

详情见链接:http://www.cnblogs.com/hjy9420/p/5032309.html

3)二分查找
算法思想:又叫折半查找,要求待查找的序列有序。每次取中间位置的值与待查关键字比较,如果中间位置的值比待查关键字大,则在前半部分循环这个查找的过程,如果中间位置的值比待查关键字小,则在后半部分循环这个查找的过程。直到查找到了为止,否则序列中没有待查的关键字。
int binarySearch(int[] a, int value){
        int low = 0;//定义数组下标的最小值
        int high = a.length-1; //定义数组下标的最大值
        while(low <= high){
                mid = (low+high)/2; //mid为数组下标的中间值
//如果如果数组中间值下标的值等于value,则返回下标中间值
                if (a[mid] == value)
                        return mid;
//如果数组中间值下标的值大于value,则数组下标的最大值为下标中间值减去1,否则数组下标最小值为下标中间值加上1
                else if (a[mid] > value)
                        high = mid-1;
                else
                        low = mid +1;
        }
        return -1;
}
** mid = (low + high) / 2; 有问题,当low + high大于int范围时就会溢出的。Sun的jdk里面的二分查找源码原先也有同样的问题。
    解决的方法是mid = low/2 + high/2。这样用2先除一下,就不会溢出了。
详情见链接: http://android.blog.51cto.com/268543/130450/

3) 二分查找
int binarySearch( int[] a, int value){
         int low = 0;//定义数组下标的最小值
         int high = a.length-1; //定义数组下标的最大值
        
         while(low <= high){
                mid = (low+high)/2; //mid为数组下标的中间值
//如果如果数组中间值下标的值等于value,则返回下标中间值
                 if (a[mid] == value)
                         return mid;
//如果如果数组中间值下标的值大于value,则数组下标的最大值为下标中间值减去1,否则数组下标最小值为下标中间值加上1
                 else if (a[mid] > value)
                        high = mid-1;
                 else
                        low = mid +1;
        }
         return -1;
}
** mid = (low + high) / 2; 有问题,当low + high大于int范围时就会溢出的。Sun的jdk里面的二分查找源码原先也有同样的问题。
    解决的方法是mid = low/2 + high/2。这样用2先除一下,就不会溢出了。


二十六.Equals和==区别?

1、 ==是判断两个变量或实例是不是指向同一个内存空间

      equals是判断两个变量或实例所指向的内存空间的值是不是相同

2、==是指对内存地址进行比较

     equals()是对字符串的内容进行比较

3、==指引用是否相同

     equals()指的是值是否相同

二十七.在子线程中如何更新UI?

第一种用 Handler

在主线程中定义Handler,通知Handler完成UI更新;

第二种用 用Activity对象的runOnUiThread方法更新UI;

第三种用 View.post(Runnable r) ;

总结:UI的更新必须在主线程中完成,所以不管上述那种方法,都是将更新UI的消息发送到了主线程的消息对象,让主线程做处理;

二十八.Handler原理

Handler主要用于线程间的通信。

一个Handler允许发送和处理Message和Runable对象,UI主线程会自动分配一个Looper(消息轮询器),每个Looper中封装着MessageQueue(消息队列),遵循先进先出原则。Looper负责不断的从自己的消息队列里取出队头的任务或消息执行。一般是在子线程执行完耗时操作之后,通过Handler的sendMessage或post方法将Message和Runable对象传递给MessageQueue,而且在这些对象离开MessageQueue时,Handler负责执行他们(用到handleMessage方法,主要执行刷新UI的代码)。

二十九. Java中常用的数据结构?

点击打开链接

java中有几种常用的数据结构,主要分为Collectionmap两个主要接口(接口只提供方法,并不提供实现),而程序中最终使用的数据结构是继承自这些接口的数据结构类。其主要的关系(继承关系)有:

Collection---->Collections                                                                                                          Map----->SortedMap------>TreeMap

Collection---->List----->(Vector \ ArryList \ LinkedList)                                                          Map------>HashMap----->TreeMap----->HashTable

Collection---->Set------>(HashSet \ LinkedHashSet \ SortedSet)

List总结:

所有的List中可以有相同的元素,可以有null元素,

基于Array的List(Vector,ArrayList)适合查询,而LinkedList 适合添加,删除操作

Set总结:

Set是不包含重复元素的Collection;

Set中的元素是不能重复的,如果使用add(Object obj)方法添加已经存在的对象,则会覆盖前面的对象

HashSet和TreeSet的区别?

1、TreeSet 是二差树实现的,Treeset中的数据是自动排好序的,不允许放入null值。 

2、HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束。 

3、HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的 String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例 。

Map总结:

Map有:HashMap、TreeMap、Hashtable。
    1、HashMap:线程不安全,键、值不允许为null,并且没顺序。
    2、Hashtable:线程安全,键、值允许为null,并且没顺序。
    3、TreeMap:线程不安全、键、值不允许为null,并且没顺序。
备注:当前用的最多的是HashMap,因为线性不安全,也就是说读取和存储效率要更高一些。

几个常用类的区别 :

1.ArrayList: 元素单个,效率高,多用于查询 
2.Vector: 元素单个,线程安全,多用于查询 
3.LinkedList:元素单个,多用于插入和删除 
4.HashMap: 元素成对,元素可为空 
5.HashTable: 元素成对,线程安全,元素不可为空

HashSet:元素无序、不可重复;ArrayList:元素有序,可重复

HashMap以键值对的形式保存数据,key值可重复,value值不可重复

三十.多线程的应用

多线程一个是利用现在CPU的多核机制,可以提供并行能力
另一个是实现异步处理,不会阻塞主线程,可以提供更好的用户体验

哪些场景用到多线程?

    场景一:一个业务逻辑有很多次的循环,每次循环之间没有影响,比如验证1万条url路径是否存在,正常情况要循环1万次,
逐个去验证每一条URL,这样效率会很低,假设验证一条需要1分钟,总共就需要1万分钟,有点恐怖。这时可以用多线程,
将1万条URL分成50等份,开50个线程,没个线程只需验证200条,这样所有的线程执行完是远小于1万分钟的。

   场景二:需要知道一个任务的执行进度,比如我们常看到的进度条,实现方式可以是在任务中加入一个整型属性变量(这样
不同方法可以共享),任务执行一定程度就给变量值加1,另外开一个线程按时间间隔不断去访问这个变量,并反馈给用户。

   总之使用多线程就是为了充分利用cpu的资源,提高程序执行效率,当你发现一个业务逻辑执行效率特别低,耗时特别长,
就可以考虑使用多线程。不过CPU执行哪个线程的时间和顺序是不确定的,即使设置了线程的优先级,因此使用多线程的风险
也是比较大的,会出现很多预料不到的问题,一定要多熟悉概念,多构造不同的场景去测试才能够掌握!

三十一.BitMap图片的二次采样(防止加载图片时出现oom)

具体代码实现

1.第一次采样

第一次采样我主要是想要获得图片的压缩比例(加载图片的边界到内存,获得图片的宽高参数,从而计算出缩放比例)

假如说我有一张图片是200*200,那么我想把这张图片的缩略图显示在一个50*50的ImageView上,那我的压缩比例应该为4,那么这个4应该怎么样来获得呢?这就是我们第一步的操作了,我先加载图片的边界到内存中,这个加载操作并不会耗费多少内存,加载到内存之后,我就可以获得这张图片的宽高参数,然后根据图片的宽高,再结合控件的宽高计算出缩放比例。

2.第二次采样

二次采样的时候,我把第一次采样后算出来的结果作为一个参数传递给第BitmapFactory,这样在加载图片的时候系统就不会将整张图片加载进来了,而是只会加载该图片的一张缩略图进来,这样不仅提高了加载速率,而且也极大的节省了内存,而且对于用户来说,他也不会有视觉上的差异。

三十二.常用的存储方式有哪些?

SQLite:

SQLite是一个轻量级的数据库,支持基本SQL语法,是常被采用的一种数据存储方式。Android为此数据库提供了一个名为SQLiteDatabase的类,封装了一些操作数据库的API

SharedPreference

SQLite数据库外,另一种常用的数据存储方式,其本质就是一个xml文件,常用于存储较简单的参数设置

File:

即常说的文件(I/O)存储方法,常用于存储大数量的数据,但是缺点是更新数据将是一件困难的事情。

ContentProvider:

Android 系统中能实现所有应用程序共享的一种数据存储方式,由于数据通常在各应用间的是互相私密的,所以此存储方式较少使用,但是其又是必不可少的一种存储方式例如音频,视频,图片和通讯录,一般都可以采用此种方式进行存储。每个ContentProvider都会对外提供一个公共的URI(包装成Uri对 象),如果应用程序有数据需要共享时,就需要使用ContentProvider为这些数据定义一个URI,然后其他的应用程序就通过 Content Provider传入这个URI来对数据进行操作。

网络存储:

从网络读取数据和写入数据 Android提供了通过网络来实现数据的存储和获取的方法。

我们可以调用WebService返回的数据或是解析HTTP协议实现网络数据交互。

三十三.线程之间的通信方式(如何避免ANR)

1). AsyncTask,其中doInBackground()onPostExecute(Result)两个方法非常重要

doInBackground() 这个方法运行在后台线程中,主要负责执行那些很耗时的操作,如访问网络。该方法必须重写。

onPostExecute(Result) 这个方法运行于UI主线程,在doInBackground(Params…)方法执行后调用,该方法用于接收后台任务执行后返回的结果,刷新UI显示。

2.)子线程 + handler

在子线程中执行完耗时操作需要刷新UI时,通过handler.sendMessage()发消息给主线程, 然后在主线Handler中的handleMessage()方法中执行刷新UI操作。

三十四.Activity的生命周期?

七个,oncreate,onstart,onresume(重新开始),onpause(暂停),onstop(停止)onrestart,ondestroy,;(清楚整个周期的过程)

A-B(由A跳转到B) A先onpause到B运行oncreate onstart然后是onresume(获取焦点) 最后是A(失去焦点)运行onstop。

1).启动Activity:系统会先调用onCreate方法,然后调用onStart方法,最后调用onResume,Activity进入运行状态。

2).当前Activity被其他Activity覆盖其上或被锁屏:系统会调用onPause方法,暂停当前Activity的执行。

3).当前Activity由被覆盖状态回到前台或解锁屏:系统会调用onResume方法,再次进入运行状态。

4).当前Activity转到新的Activity界面或按Home键回到主屏,自身退居后台:系统会先调用onPause方法,然后调用onStop方法,进入停滞状态。

5).用户后退回到此Activity:系统会先调用onRestart方法,然后调用onStart方法,最后调用onResume方法,再次进入运行状态。

6).当前Activity处于被覆盖状态或者后台不可见状态,即第2步和第4步,系统内存不足,杀死当前Activity,而后用户退回当前Activity:再次调用onCreate方法、onStart方法、onResume方法,进入运行状态。

7).用户退出当前Activity:系统先调用onPause方法,然后调用onStop方法,最后调用onDestory方法,结束当前Activity。

Activity的任务栈?

先进后出

三十五 .Fragment生命周期?

Android------面试简答题_第4张图片

Fragment为什么被称为第五大组件

Fragment比Activity更节省内存,其切换模式也更加舒适,使用频率不低于四大组件,且有自己的生命周期,而且必须依附于Activity

FragmentPageAdapter和FragmentPageStateAdapter的区别

FragmentPageAdapter在每次切换页面的的时候,是将Fragment进行分离,适合页面较少的Fragment使用以保存一些内存,对系统内存不会多大影响

FragmentPageStateAdapter在每次切换页面的时候,是将Fragment进行回收,适合页面较多的Fragment使用,这样就不会消耗更多的内存




三十六.Service(服务)和Thread(线程)的区别?

1).ThreadThread 是程序执行的最小单元,它是分配CPU的基本单位。可以用 Thread 来执行一些异步的操作。 

2).ServiceService 是android的一种机制,当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的

Service是安卓中系统的组件,它运行在独立进程的主线程中,不可以执行耗时操作。Thread是程序执行的最小单元,分配CPU的基本单位,可以开启子线程执行耗时操作

Service在不同Activity中可以获取自身实例,可以方便的对Service进行操作。Thread在不同的Activity中难以获取自身实例,如果Activity被销毁,Thread实例就很难再获取得到

三十七.面向对象的特征?

封装

封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。

封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

继承

面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

多态

多态的定义指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)

说白了就是:同一个事件发生在不同的对象上会产生不同的结果。

实现多态,有二种方式,覆盖,重载。

覆盖,是指子类重新定义父类的虚函数的做法。

重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。

方法的重载属于,编译时多态,方法名相同参数列表不同,返回值必须相同或都没有返回值类型。        

方法的覆盖属于运行时多态,子类覆盖父类的方法,子类指向父类引用,在调用方法的时候用父类的引用调用。

多态存在的三个必要条件:
一、要有继承;
二、要有重写;
三、父类引用指向子类对象

多态的好处:

1.可替换性(substitutability)。多态对已存在代码具有可替换性

2. 可扩充性(extensibility)。多态对代码具有可扩充性

3.接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的

4.灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
5.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。

三十八.Final Finally Finalized 区别?

final 用于声明属性,方法和类,分别表示性不可变,方法不可覆盖,类不

可继承。

finally 异常处理语句结构的一部分,表示总是执行。

finalize Object类的一个方法在垃圾收集器执行的时候会调用被回收对象的此

方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。

三十九.NDK是什么?

NDK 是 Native Development Kit 的简称。它是一个工具集,集成了 Android 的交叉编译环境,并提供了一套比较方便的 Makefile ,可以帮助开发者快速开发 C 或是 C++ 的动态库,并自动的将 so 和 java 程序打包成 apk ,在 Android 上运行。Android 上,应用程序的开发,大部分基于 Java 语言来实现。要使用 c 或是 c++ 的程序或库,就需要使用 NDK 来实现。

四十.安卓的系统架构?

应用层:使用Java语言进行开发的一些应用程序

应用框架层:主要是谷歌发布的一些操作支持的类库(API框架),开发人员可以使用这些类库方便的进行程序开发,但是在开发时必须遵守框架的开发原则

系统运行库层:当使用安卓框架层进行开发时,安卓操作系统会自动使用一些c/c++的库文件来支持所使用的各个组件,使其可以更好的为程序服务;

Linux内核层:安卓操作系统主要是基于Linux内核,程序的安全性,驱动程序,进程管理等都由Linux内核提供。

四十一.OnTouch和OnTouchEvent区别?

1.onTouch方法
onTouch方法是View的 OnTouchListener接口中定义的方法。
当一个View绑定了OnTouchLister后,当有touch事件触发时,就会调用onTouch方法。
(当把手放到View上后,onTouch方法被一遍一遍地被调用)

2.onTouchEvent方法
onTouchEvent方法是override 的Activity的方法。
重写了Activity的onTouchEvent方法后,当屏幕有touch事件时,此方法就会别调用。

四十二. APP版本更新,数据库的更新

APP版本更新:

在清单文件更改版本号,上传更新的应用到平台,利用平台的更新提醒用户是否更新新版本。

数据库更新:
先更改版本号,在onupgress方法内判断版本号是否一致,不一致则更新数据库。

四十三.移动互联数据的交换格式?
移动互联数据交互格式有XMLJSON

共同点:

1.JSONXML的数据可读性基本相同

2.JSONXML同样拥有丰富的解析手段

Json的优势:

3.JSON相对于XML来讲数据的体积小

4.JSONJavaScript的交互更加方便

5.JSON对数据的描述性比XML较差

6.JSON速度要远远快于XML

四十四.线程相关?

定义:

线程被称为轻量级进程,是程序执行流的最小单元,是进程的一个实体。有就绪,阻塞,运行 三种基本状态。

多线程定义:

在单个程序中同时运行多个线程完成不同的工作。

线程和进程的区别:

进程定义:

进程是系统进行资源分配和调度的一个独立单位。

关系:

一个线程可以创建和撤销另一个线程,同一个进程中的多个线程可以同时并发执行,他可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行顺序

1一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。  2)资源分配给进程,同一进程的所有线程共享该进程的所有资源  

3)处理机分给线程,即真正在处理机上运行的是线程  

4)线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。


区别:

他们是不同的操作系统资源管理方式

进程有独立的地址空间,一个进程崩溃后,不会对其他进程产生影响

线程只是一个进程中不同的执行路径,线程有自己的堆栈和局部变量,线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,  所以多线程的操作要比多进程的程序健壮。   但在进程切换时耗费资源较大,效率要差一些

对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程

因为进程在切换时耗费的资源要大一些,效率差

进程的优先级?
空进程
后台进程
服务进程
可见进程
前台进程

四十五.XML有几种解析方式?区别?

三种:DOM SAX PULL

DOM 将XML文件的所有内容读取到内存中,

优点是对文档增删改查比较方便,缺点占用内存比较大

SAX 是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备 缺点是只适合做文档的读取,不适合做文档的增删改,不能中途停止。

PULL 与SAX相似,可随时终止,调用next() 方法提取它们(主动提取事件)

四十六.访问网络如何加密?

1对称加密(DES,AES)和非对称(RSA公钥与私钥),(支付宝里的商户的公钥和私钥)一般用到的HTTPS加密是结合对称加密和非对称加密来进行加密(利用对称加密的快捷性加密报文和非对称加密的安全性进行)

2MD5(算法)

3Base64

四十七.手机横竖屏切换时Activity生命周期的变化

点击打开详情

2、运行Activity,得到如下信息
onCreate-->
onStart-->
onResume-->

3.切换成横屏
onSaveInstanceState-->
onPause-->
onStop-->
onDestroy-->
onCreate-->
onStart-->
onRestoreInstanceState-->
onResume-->

4、再切换成竖屏时,发现打印了两次相同的log
onSaveInstanceState-->
onPause-->
onStop-->
onDestroy-->
onCreate-->
onStart-->
onRestoreInstanceState-->
onResume-->

onSaveInstanceState-->
onPause-->
onStop-->
onDestroy-->
onCreate-->
onStart-->
onRestoreInstanceState-->
onResume-->
5、修改AndroidManifest.xml,把该Activity添加
android:configChanges="orientation"
切换横屏时生命周期运行一次。
onSaveInstanceState-->
onPause-->
onStop-->
onDestroy-->
onCreate-->
onStart-->
onRestoreInstanceState-->
onResume-->

6、再切换竖屏时,发现不会再打印相同信息,但多打印了一行onConfigChanged
onSaveInstanceState-->
onPause-->
onStop-->
onDestroy-->
onCreate-->
onStart-->
onRestoreInstanceState-->
onResume-->
onConfigurationChanged-->

7、把步骤5的android:configChanges="orientation" 改成
android:configChanges="orientation|keyboardHidden"切换横屏时,就只打印
onConfigChanged
onConfigurationChanged-->
8、切换竖屏时
onConfigurationChanged-->
onConfigurationChanged-->
总结:
1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,
切横屏时会执行一次,切竖屏时会执行两次
2、设置Activity的android:configChanges="orientation"时,切屏还是会重新调
用各个生命周期,切横、竖屏时只会执行一次
3、设置Activity的android:configChanges="orientation|keyboardHidden"时,
切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

总结一下整个Activity的生命周期
补充一点,当前Activity产生事件弹出Toast和AlertDialog的时候Activity的生命
周期不会有改变
Activity运行时按下HOME键(跟被完全覆盖是一样的):onSaveInstanceState -->
onPause --> onStop onRestart -->onStart--->onResume
Activity未被完全覆盖只是失去焦点:onPause--->onResume

onSavedInstanceState()和onRestoreInstanceState()并不是activity生命周期的方法。

onSaveInstanceState()会在onPause()或onStop()之前执行,onRestoreInstanceState()会在onStart()和onResume()之间执行。

onSaveInstanceState()需要调用的时,activity可能销毁,也可能没有销毁,只有在activity销毁重建的时候onRestoreInstanceState()才会调用。


四十八.JNI与NDK的区别?

JNI:是一套编程接口,用来实现Java代码与本地的C/C++代码进行交互。
NDK: NDK是Google开发的一套开发和编译工具集,可以生成动态链接库,主要用于Android的JNI开发;

JNI的作用:

扩展:JNI扩展了JVM能力,驱动开发,例如开发一个wifi驱动,可以将手机设置为无限路由;

高效: 本地代码效率高,游戏渲染,音频视频处理等方面使用JNI调用本地代码,C语言可以灵活操作内存;

复用: 在文件压缩算法 7zip开源代码库,机器视觉 OpenCV开放算法库等方面可以复用C平台上的代码,不必在开发一套完整的Java体系,避免重复发明轮子;

特殊: 产品的核心技术一般也采用JNI开发,不易破解;

JNI在Android中的作用:

JNI可以调用本地代码库(即C/C++代码),并通过 Dalvik 虚拟机与应用层和应用框架层进行交互,Android中JNI代码主要位于应用层和应用框架层;

应用层: 该层是由JNI开发,主要使用标准JNI编程模型;

应用框架层: 使用的是Android中自定义的一套JNI编程模型,该自定义的JNI编程模型弥补了标准JNI编程模型的不足;

四十九.CMake的理解?

CMake是什么?

CMake 是一个开源的跨平台自动化构建系统

CMake的特点:
1)开放源代码,使用类 BSD 许可发布。 2)跨平台,并可生成 native 编译配置文件,在 Linux/Unix 平台,生成 makefile,在
Mac 平台,可以生成 xcode,在 Windows 平台,可以生成 MSVC 的工程文件。
3)能够管理大型项目; 4)简化编译构建过程和编译过程。Cmake 的工具链非常简单:cmake+make。 5)高效率; 6)可扩展,可以为 cmake 编写特定功能的模块,扩充 cmake 功能。
五十.Handler Thread了解

1、HandlerThread产生背景

当系统有多个耗时任务需要执行时,每个任务都会开启一个新线程去执行耗时任务,这样会导致系统多次创建和销毁线程,从而影响性能。为了解决这一问题,Google提供了HandlerThread,HandlerThread是在线程中创建一个Looper循环器,让Looper轮询消息队列,当有耗时任务进入队列时,则不需要开启新线程,在原有的线程中执行耗时任务即可,否则线程阻塞。

2、HanlderThread的特点

  • HandlerThread本质上是一个线程,继承自Thread

  • HandlerThread有自己的Looper对象,可以进行Looper循环,可以创建Handler

  • HandlerThread可以在Handler的handlerMessage中执行异步方法

  • HandlerThread优点是异步不会堵塞,减少对性能的消耗

  • HandlerThread缺点是不能同时继续进行多任务处理,需要等待进行处理,处理效率较低

  • HandlerThread与线程池不同,HandlerThread是一个串行队列,背后只有一个线程。

五十一. IntentService是什么?

ntentService是继承自Service并处理异步请求的一个类,其内部采用HandlerThread和Handler实现的,在IntentService内有一个工作线程来处理耗时操作,其优先级比普通Service高。当任务完成后,IntentService会自动停止,而不需要手动调用stopSelf()。另外,可以多次启动IntentService,每个耗时操作都会以工作队列的方式在IntentService中onHandlerIntent()回调方法中执行,并且每次只会执行一个工作线程

IntentService使用方法

创建Service继承自IntentService

覆写构造方法和onHandlerIntent()方法

在onHandlerIntent()中执行耗时操作

五十二.String buffer 与string builder 的区别?

 String 字符串常量
StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)

三者在执行速度方面的比较:StringBuilder >  StringBuffer  >  String

五十三.Java中的四种引用?

强 软 弱 虚

强引用
只要某个对象有强引用与之关联,JVM必定不会回收这个对象,即使在内存不足的情况下,JVM宁愿抛出OutOfMemory错误也不会回收这种对象

软引用

软引用是用来描述一些有用但并不是必需的对象,只有在内存不足的时候JVM才会回收该对象

弱引用

弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象

虚引用

虚引用和前面的软引用、弱引用不同,它并不影响对象的生命周期。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。

五十四. TCP四次挥手?

所谓四次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。

由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,

Android------面试简答题_第5张图片

  • 第一次挥手:
    Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
  • 第二次挥手:
    Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
  • 第三次挥手:
    Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
  • 第四次挥手:
    Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
实际中还会出现同时发起主动关闭的情况。

五十五. Android线程产生死锁的四个必要条件?

死锁:指两个或两个以上的进程进在执行过程中,由于资源竞争或由于相互通信而造成的一种阻塞式现象,如果没有外力影响。那么它们将永远的持续下去, 此事称系统产生死锁现象,这种永远互相在等待的进程成为死锁。
产生死锁的必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 占有且等待:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3)不可强行占有:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。
产生死锁的原因:
(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适。
(3) 资源分配不当等。
如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则

就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。

处理死锁的方法:

*死锁预防:通过设置某些限制条件,去破坏死锁的四个条件中的一个或几个条件,来预防发生死锁。但由于所施加的限制条件往往太严格,因而导致系统资源利用率和系统吞吐量降低。

*死锁避免:允许前三个必要条件,但通过明智的选择,确保永远不会到达死锁点,因此死锁避免比死锁预防允许更多的并发。

*死锁检测:不须实现采取任何限制性措施,而是允许系统在运行过程发生死锁,但可通过系统设置的检测机构及时检测出死锁的发生,并精确地确定于死锁相关的进程和资源,然后采取适当的措施,从系统中将已发生的死锁清除掉。

*死锁解除:与死锁检测相配套的一种措施。当检测到系统中已发生死锁,需将进程从死锁状态中解脱出来。常用方法:撤销或挂起一些进程,以便回收一些资源,再将这些资源分配给已处于阻塞状态的进程。死锁检测盒解除有可能使系统获得较好的资源利用率和吞吐量,但在实现上难度也最大。


五十六.View SurfaceView GLsurfaceView的区别与联系?

在2D游戏开发中,大致可以分为两种游戏框架,View和SurfaceView。

 View和SurfaceView区别:

View:必须在UI的主线程中更新画面,用于被动更新画面

surfaceView:UI线程和子线程中都可以。在一个新启动的线程中重新绘制画面,主动更新画面。

GLSurfaceView:基于SurfaceView视图再次进行拓展的视图类,专用于3D游戏开发的视图;是SurfaceView的子类,openGL专用。










































































 
  




你可能感兴趣的:(Android------面试简答题)