算法思想:又叫折半查找,要求待查找的序列有序。每次取中间位置的值与待查关键字比较,如果中间位置的值比待查关键字大,则在前半部分循环这个查找的过程,如果中间位置的值比待查关键字小,则在后半部分循环这个查找的过程。直到查找到了为止,否则序列中没有待查的关键字。
//如果如果数组中间值下标的值等于value,则返回下标中间值
//如果数组中间值下标的值大于value,则数组下标的最大值为下标中间值减去1,否则数组下标最小值为下标中间值加上1
//如果如果数组中间值下标的值等于value,则返回下标中间值
//如果如果数组中间值下标的值大于value,则数组下标的最大值为下标中间值减去1,否则数组下标最小值为下标中间值加上1
1、 ==是判断两个变量或实例是不是指向同一个内存空间
2、==是指对内存地址进行比较
3、==指引用是否相同
二十七.在子线程中如何更新UI?
总结:UI的更新必须在主线程中完成,所以不管上述那种方法,都是将更新UI的消息发送到了主线程的消息对象,让主线程做处理;
Handler主要用于线程间的通信。
一个Handler允许发送和处理Message和Runable对象,UI主线程会自动分配一个Looper(消息轮询器),每个Looper中封装着MessageQueue(消息队列),遵循先进先出原则。Looper负责不断的从自己的消息队列里取出队头的任务或消息执行。一般是在子线程执行完耗时操作之后,通过Handler的sendMessage或post方法将Message和Runable对象传递给MessageQueue,而且在这些对象离开MessageQueue时,Handler负责执行他们(用到handleMessage方法,主要执行刷新UI的代码)。
二十九. Java中常用的数据结构?
java中有几种常用的数据结构,主要分为Collection和map两个主要接口(接口只提供方法,并不提供实现),而程序中最终使用的数据结构是继承自这些接口的数据结构类。其主要的关系(继承关系)有:
所有的List中可以有相同的元素,可以有null元素,
Set中的元素是不能重复的,如果使用add(Object obj)方法添加已经存在的对象,则会覆盖前面的对象;
2、HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束。
3、HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的 String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例 。
1、HashMap:线程不安全,键、值不允许为null,并且没顺序。 2、Hashtable:,键、值允许为null,并且没顺序。 3、TreeMap:线程不安全、键、值不允许为null,并且没顺序。 备注:当前用的最多的是HashMap,因为线性不安全,也就是说读取和存储效率要更高一些。HashSet:元素无序、不可重复;ArrayList:元素有序,可重复
HashMap以键值对的形式保存数据,key值可重复,value值不可重复
多线程一个是利用现在CPU的多核机制,可以提供并行能力
另一个是实现异步处理,不会阻塞主线程,可以提供更好的用户体验
场景一:一个有很多次的循环,每次循环之间没有影响,比如验证1万条url路径是否存在,正常情况要循环1万次,
逐个去验证每一条URL,这样效率会很低,假设验证一条需要1分钟,总共就需要1万分钟,有点恐怖。这时可以用多线程,
将1万条URL分成50等份,开50个线程,没个线程只需验证200条,这样所有的线程执行完是远小于1万分钟的。
场景二:需要知道一个任务的执行进度,比如我们常看到的进度条,实现方式可以是在任务中加入一个整型属性变量(这样
不同方法可以共享),任务执行一定程度就给变量值加1,另外开一个线程按时间间隔不断去访问这个变量,并反馈给用户。
总之使用多线程就是为了充分利用cpu的资源,提高程序执行效率,当你发现一个执行效率特别低,耗时特别长,
就可以考虑使用多线程。不过CPU执行哪个线程的时间和顺序是不确定的,即使设置了线程的优先级,因此使用多线程的风险
也是比较大的,会出现很多预料不到的问题,一定要多熟悉概念,多构造不同的场景去测试才能够掌握!
SQLite是一个轻量级的数据库,支持基本SQL语法,是常被采用的一种数据存储方式。Android为此数据库提供了一个名为SQLiteDatabase的类,封装了一些操作数据库的API。
除SQLite数据库外,另一种常用的数据存储方式,其本质就是一个xml文件,常用于存储较简单的参数设置
即常说的文件(I/O)存储方法,常用于存储大数量的数据,但是缺点是更新数据将是一件困难的事情。
系统中能实现所有应用程序共享的一种数据存储方式,由于数据通常在各应用间的是互相私密的,所以此存储方式较少使用,但是其又是必不可少的一种存储方式。例如音频,视频,图片和通讯录,一般都可以采用此种方式进行存储。每个ContentProvider都会对外提供一个公共的URI(包装成Uri对 象),如果应用程序有数据需要共享时,就需要使用ContentProvider为这些数据定义一个URI,然后其他的应用程序就通过 Content Provider传入这个URI来对数据进行操作。
从网络读取数据和写入数据。 Android提供了通过网络来实现数据的存储和获取的方法。
我们可以调用WebService返回的数据或是解析HTTP协议实现网络数据交互。
三十三.线程之间的通信方式(如何避免ANR)
doInBackground() 这个方法运行在后台线程中,主要负责执行那些很耗时的操作,如访问网络。该方法必须重写。
3).当前Activity由被覆盖状态回到前台或解锁屏:系统会调用onResume方法,再次进入运行状态。
4).当前Activity转到新的Activity界面或按Home键回到主屏,自身退居后台:系统会先调用onPause方法,然后调用onStop方法,进入停滞状态。
5).用户后退回到此Activity:系统会先调用onRestart方法,然后调用onStart方法,最后调用onResume方法,再次进入运行状态。
6).当前Activity处于被覆盖状态或者后台不可见状态,即第2步和第4步,系统内存不足,杀死当前Activity,而后用户退回当前Activity:再次调用onCreate方法、onStart方法、onResume方法,进入运行状态。
FragmentPageAdapter在每次切换页面的的时候,是将Fragment进行分离,适合页面较少的Fragment使用以保存一些内存,对系统内存不会多大影响
Service是安卓中系统的组件,它运行在独立进程的主线程中,不可以执行耗时操作。Thread是程序执行的最小单元,分配CPU的基本单位,可以开启子线程执行耗时操作
Service在不同Activity中可以获取自身实例,可以方便的对Service进行操作。Thread在不同的Activity中难以获取自身实例,如果Activity被销毁,Thread实例就很难再获取得到
三十七.面向对象的特征?
封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。
封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
说白了就是:同一个事件发生在不同的对象上会产生不同的结果。
实现多态,有二种方式,覆盖,重载。
覆盖,是指子类重新定义父类的虚函数的做法。
重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。
方法的重载属于,编译时多态,方法名相同参数列表不同,返回值必须相同或都没有返回值类型。
方法的覆盖属于运行时多态,子类覆盖父类的方法,子类指向父类引用,在调用方法的时候用父类的引用调用。
多态存在的三个必要条件:
三、父类引用指向子类对象。
1.可替换性(substitutability)。多态对已存在代码具有可替换性
2.可扩充性(extensibility)。多态对代码具有可扩充性
3.接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的
4.灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
5.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。
final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不
finally 是异常处理语句结构的一部分,表示总是执行。
finalize 是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此
方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。
三十九.NDK是什么?
语言来实现。要使用 c 或是 c++ 的程序或库,就需要使用 NDK 来实现。
四十.安卓的系统架构?
应用层:使用Java语言进行开发的一些应用程序
应用框架层:主要是谷歌发布的一些操作支持的类库(API框架),开发人员可以使用这些类库方便的进行程序开发,但是在开发时必须遵守框架的开发原则
系统运行库层:当使用安卓框架层进行开发时,安卓操作系统会自动使用一些c/c++的库文件来支持所使用的各个组件,使其可以更好的为程序服务;
Linux内核层:安卓操作系统主要是基于Linux内核,程序的安全性,驱动程序,进程管理等都由Linux内核提供。
四十二. APP版本更新,数据库的更新
在清单文件更改版本号,上传更新的应用到平台,利用平台的更新提醒用户是否更新新版本。
先更改版本号,在onupgress方法内判断版本号是否一致,不一致则更新数据库。
四十三.移动互联数据的交换格式?
移动互联数据交互格式有XML和JSON
1.JSON和XML的数据可读性基本相同
2.JSON和XML同样拥有丰富的解析手段
3.JSON相对于XML来讲,数据的体积小
5.JSON对数据的描述性比XML较差
线程被称为轻量级进程,是程序执行流的最小单元,是进程的一个实体。有就绪,阻塞,运行 三种基本状态。
在单个程序中同时运行多个线程完成不同的工作。
进程是系统进行资源分配和调度的一个独立单位。
一个线程可以创建和撤销另一个线程,同一个进程中的多个线程可以同时并发执行,他可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行顺序
(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。 (2)资源分配给进程,同一进程的所有线程共享该进程的所有资源。
(3)处理机分给线程,即真正在处理机上运行的是线程。
(4)线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。
他们是不同的操作系统资源管理方式。
进程有独立的地址空间,一个进程崩溃后,不会对其他进程产生影响
线程只是一个进程中不同的执行路径,线程有自己的堆栈和局部变量,线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉, 所以多线程的操作要比多进程的程序健壮。 但在进程切换时耗费资源较大,效率要差一些
对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程,
(因为进程在切换时耗费的资源要大一些,效率差
四十五.XML有几种解析方式?区别?
DOM 将XML文件的所有内容读取到内存中,
优点是对文档增删改查比较方便,缺点占用内存比较大
SAX 是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备,缺点是只适合做文档的读取,不适合做文档的增删改,不能中途停止。
PULL 与SAX相似,可随时终止,调用next() 方法提取它们(主动提取事件)
四十六.访问网络如何加密?
1:对称加密(DES,AES)和非对称(RSA公钥与私钥),(支付宝里的商户的公钥和私钥)一般用到的HTTPS加密是结合对称加密和非对称加密来进行加密(利用对称加密的快捷性加密报文和非对称加密的安全性进行)
四十七.手机横竖屏切换时Activity生命周期的变化
四十八.JNI与NDK的区别?
JNI:是一套编程接口,用来实现Java代码与本地的C/C++代码进行交互。
NDK: NDK是Google开发的一套开发和编译工具集,可以生成动态链接库,主要用于Android的JNI开发;
扩展:JNI扩展了JVM能力,驱动开发,例如开发一个wifi驱动,可以将手机设置为无限路由;
高效: 本地代码效率高,游戏渲染,音频视频处理等方面使用JNI调用本地代码,C语言可以灵活操作内存;
复用: 在文件压缩算法 7zip开源代码库,机器视觉 OpenCV开放算法库等方面可以复用C平台上的代码,不必在开发一套完整的Java体系,避免重复发明轮子;
特殊: 产品的核心技术一般也采用JNI开发,不易**;
JNI可以调用本地代码库(即C/C++代码),并通过 Dalvik 虚拟机与应用层和应用框架层进行交互,Android中JNI代码主要位于应用层和应用框架层;
应用层: 该层是由JNI开发,主要使用标准JNI编程模型;
应用框架层: 使用的是Android中自定义的一套JNI编程模型,该自定义的JNI编程模型弥补了标准JNI编程模型的不足;
四十九.CMake的理解?
CMake 是一个开源的跨平台自动化构建系统
1)开放源代码,使用类 BSD 许可发布。2)跨平台,并可生成 native 编译配置文件,在 Linux/Unix 平台,生成 makefile,在
Mac 平台,可以生成 xcode,在 Windows 平台,可以生成 MSVC 的工程文件。3)能够管理大型项目;4)简化编译构建过程和编译过程。Cmake 的工具链非常简单:cmake+make。5)高效率;6)可扩展,可以为 cmake
编写特定功能的模块,扩充
当系统有多个耗时任务需要执行时,每个任务都会开启一个新线程去执行耗时任务,这样会导致系统多次创建和销毁线程,从而影响性能。为了解决这一问题,Google提供了HandlerThread,HandlerThread是在线程中创建一个Looper循环器,让Looper轮询消息队列,当有耗时任务进入队列时,则不需要开启新线程,在原有的线程中执行耗时任务即可,否则线程阻塞。
HandlerThread优点是异步不会堵塞,减少对性能的消耗
HandlerThread缺点是不能同时继续进行多任务处理,需要等待进行处理,处理效率较低
五十三.Java中的四种引用?
只要某个对象有强引用与之关联,JVM必定不会回收这个对象,即使在内存不足的情况下,JVM宁愿抛出OutOfMemory错误也不会回收这种对象;
软引用是用来描述一些有用但并不是必需的对象,只有在内存不足的时候JVM才会回收该对象。
弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。
虚引用和前面的软引用、弱引用不同,它并不影响对象的生命周期。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。
五十四. TCP四次挥手?
所谓四次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。
由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,
实际中还会出现同时发起主动关闭的情况。
五十五. Android线程产生死锁的四个必要条件?
死锁:指两个或两个以上的进程进在执行过程中,由于资源竞争或由于相互通信而造成的一种阻塞式现象,如果没有外力影响。那么它们将永远的持续下去, 此事称系统产生死锁现象,这种永远互相在等待的进程成为死锁。
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 占有且等待:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3)不可强行占有:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。
(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适。
(3) 资源分配不当等。
如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则
就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
*死锁预防:通过设置某些限制条件,去破坏死锁的四个条件中的一个或几个条件,来预防发生死锁。但由于所施加的限制条件往往太严格,因而导致系统资源利用率和系统吞吐量降低。
*死锁避免:允许前三个必要条件,但通过明智的选择,确保永远不会到达死锁点,因此死锁避免比死锁预防允许更多的并发。
*死锁检测:不须实现采取任何限制性措施,而是允许系统在运行过程发生死锁,但可通过系统设置的检测机构及时检测出死锁的发生,并精确地确定于死锁相关的进程和资源,然后采取适当的措施,从系统中将已发生的死锁清除掉。
*死锁解除:与死锁检测相配套的一种措施。当检测到系统中已发生死锁,需将进程从死锁状态中解脱出来。常用方法:撤销或挂起一些进程,以便回收一些资源,再将这些资源分配给已处于阻塞状态的进程。死锁检测盒解除有可能使系统获得较好的资源利用率和吞吐量,但在实现上难度也最大。
在2D游戏开发中,大致可以分为两种游戏框架,View和SurfaceView。
View:必须在UI的主线程中更新画面,用于被动更新画面。
surfaceView:UI线程和子线程中都可以。在一个新启动的线程中重新绘制画面,主动更新画面。