Android面试题整理

面试问题

1、做一下自我介绍

(1)简单介绍个人信息:工作经验,教育背景以及经历

(2)讲述自己最牛逼的工作经历,以及其产生的良好效果,证明自己适合该职位:

A、推动我们安卓开发这边使用Kotlin语言开发项目,提高开发效率

具体的推动方法:

(1)在空闲时间了解和学习Kotlin语言,熟悉其用法

(2)先从业务简单的页面开始,使用Java语言开发之后,用Kotlin语言复刻开发同样的页面,然后验证其功能和使用。

(3)逐渐熟悉和掌握Kotlin语言之后,验证使用Kotlin语言开发的页面也没有其他的使用问题后,逐步开始使用Kotlin进行开发。

(4)带动同组的其他开发者从容易到复杂逐渐使用Kotlin开发。

B、替换Studio提供的打包多渠道apk的方法,使用美团开放的walle打包工具进行打包,使用python语言编写生成多渠道包的执行程序。将多渠道打包的用时从几个小时缩短到十几分钟。

2、为什么来应聘这个岗位?

首先,我对于这个行业,岗位以及所涉及的项目十分的感兴趣,同时也关注这个行业很久了,它xxxx,很xxxx,我很喜欢,很想要从事这个行业。

其次,我有丰富的相关经验,曾经通过xxxx,做了xxxx,取得了xxxx的结果,具备xxxx的能力,恰巧也是这个岗位所需要的,所以我来了。

3、你觉得你的优点是什么?

我平常一直关注最新的开发趋势,最新的开发技术,非常喜欢学习和研究新鲜有趣的技术和项目,比如之前微信推出小游戏跳一跳,github上有python编写的作弊工具,我就拿来尝试学习和研究,并用所掌握的python语言编写了用来缩短多渠道打包时间的程序。还有谷歌推出的kotlin语言,协程...都拿来尝试学习和使用,并最终都应用在开发的项目当中,既拓展了自己的技术能力,有提高了公司项目的开发效率。

4、你觉得你的缺点是什么?

我的缺点是顾虑太多,虽然这让我在决策过程中少犯了一些错误,但是在开发的时间上可能会稍微晚一点开始,所以也更加提醒了我需要注重团队协作。

另外的就是可能有点心直口快,但是基本上都是对事不对人,和同事之间造成的不愉快啊,事后也能及时的道歉,这一点在相处久了之后同事们都能够理解。

5、谈谈你离开上一家公司的原因

之前的公司一直是从事股票投资咨询方面的工作,所以所接触的业务也都是基于股票相关的东西。我想要学习和接触更多更加广阔的知识和技术。我在之前的公司干的也不错,领导也很认可我的技术能力。在我的职业上也算是到了一个瓶颈期吧,进步很慢了已经,我想要寻求更加广阔的发展空间,提升自己的技术能力和职业阅历,实现人生价值。

6、谈谈你在未来的五年职业规划

首先这是一个我非常感兴趣的行业,能够将工作和兴趣相结合是很不错的,我会认真的对待这个岗位工作,尽快的融入公司团队。在未来五年的时间内呢,我打算是学习了解掌握更多Android开发以及相关的技术知识,争取早日能够掌握一个多平台,至少是android和ios移动端的跨平台开发能力,这样的话也能胜任两端的开发工作。

7、讲述一次成功的组织活动的经历

在公司年会准备的部门节目中,组织部门的几个同事利用空闲时间,经过一个月的相互的督促和努力排练,在年会的舞台上成功的表演了一个舞蹈节目,收获了台下同事们的掌声和夸赞。

8、如果面试结果不理想,你会怎么办?

面试找工作本来就是一个双向选择的过程,我会保持平常心的,回去之后做好更加全面的准备就好。

9、你还有什么要了解的?

了解公司的晋升机制,企业文化。

团队和公司未来的发展方向。

领导对于入职之后自己在岗位上的期望。

技术面试

1、java中的==,equals,hashcode的区别。

==用来比较两个变量的值是否相等,也就是对应的内存当中的地址是否相等。基本数据类型和引用只能用==比较。

equals是object类提供的方法,和==一样,比较的是两个变量的引用是否相等,但是equals可以被覆盖,所以通过覆盖方法让其比较的不是引用而是数据内容,也就是堆中的数据是否相等。

hashcode返回的是对象的内存地址转换成的int值,所以hashcode判断是两个对象的内存地址是否相等

2、int和integer的区别

int是基本数据类型,默认值是0,直接存储数据

integer是int类型的封装对象,声明需要实例化,是一个引用指向对象,默认null

3、String,StringBuffer,StringBuilder的区别

就速度而言StringBuilder>StringBuffer>String,String是常量,一旦创建便不可更改,所有的修改都是新建对象,而StringBuilder和StringBuffer是变量,可以直接修改。在线程安全上,StringBuffer是线程安全的,而StringBuilder是线程不安全的。

4、什么是内部类,内部类的作用?

定义在一个类里边的类叫做内部类,对应的包含内部类的类叫做外部类。

内部类不允许同一包中的其他类进行访问,但是内部类可以访问外部类的所有属性、方法,包括私有数据。

内部类有四种:匿名、成员、静态、方法(局部)内部类。

5、进程和线程的区别

进程是CPU分配资源的最小单位,线程是CPU调度资源的最小单位。一个进程可以包含多个线程,但是一个线程只能属于一个进程。进程和进程之间不能共享资源,进程内的线程之间可以共享所在进程的内存地址空间。线程有自己独立的栈内存存储数据。

6、final,finally,finalize的区别

final修饰类,成员变量,成员方法,final修饰的类不可被继承,成员变量不可被修改,成员方法不可被重写。

finally和try...catch共同使用,用来使正常、异常情况最终都能得到处理。

finalize是类方法,垃圾回收之前会调用此方法,重写此方法可以实现资源回收。

7、Serializable和Parcelable的区别

Serializable是Java的序列化接口,在磁盘当中读写,读写期间产生大量的临时变量,内部执行进行大量的IO操作,效率低。

Parcelable是Android的序列化接口,在内存当中读写,效率高,但是使用麻烦,不能保存在磁盘当中。

8、静态属性和静态方法可否被继承,可否被重写?

静态属性,静态方法可以被继承,不能被重写,而是被隐藏。

当子类当中定义了静态的属性和方法,则父类的静态属性,方法称之为隐藏。

9、匿名内部类,成员内部类,静态内部类,局部内部类的理解

匿名,成员,静态,局部内部类都能独立的继承自一个接口的实现,无论外部类是否继承了一个接口的实现,对于内部类都没有影响。Java可以实现多个接口,但是只能单继承,因此内部类可以继承自多个具体或者抽象的类,来解决接口难以解决的问题,接口只是解决了部分问题,而内部类使得多继承的解决方案更加完整。

10、Java的垃圾回收机制以及它何时会被触发

垃圾回收:释放掉内存中已经没有用的对象占用的内存空间。

判断对象无用:

(1)标记法:在内存对这个对象进行标记,当这个对象被引用一次,计数加一,被释放掉计数减一,当标记为0的时候,表示这个对象可以被回收,但是对于循环引用的对象,是无法判断并回收的。

(2)根搜索法:从一个根出发,寻找所有可达的对象,而其他不可达的对象便可以进行回收。

对象可达定义:分配对象时候使用new关键字,当对象被释放掉时候将对象的引用赋值为null,让程序不能访问到这个对象,称为不可达。

何时触发垃圾回收机制:

(1)所有的实例都没有活动线程访问

(2)没有任何实例访问的循环引用实例

(3)Java中有不同的引用类型,判断对象是否符合垃圾回收的条件依赖于它的引用类型

11、Java代理是什么,静态代理和动态代理区别

当客户不想或者不能直接访问某个目标对象时候,可以通过一个第三方的代理来实现对目标对象的访问。代理可在客户端和目标对象之间起到中介作用,可以过滤掉用户不能看到的内容和服务,也可以为用户添加额外的服务。

静态代理:代理类在程序运行之前已经存在,也就是编写代码时候已经写好了代理类。

动态代理:在程序运行时候通过反射创建代理类

12、Java中实现多态的机制是什么

重写和重载时类的多态性的表现

重写是父类和子类之间多态性的表现。

重载是同一个类的多态性的表现。

13、Java中反射的相关理解

在程序运行当中,可以动态获取类的属性和方法,调用对象的方法和属性,这种动态获取信息,调用方法的机制叫做Java的反射机制。

14、Java中的注解是什么

注解,Annotation,代码级别的说明,声明在包,类,字段,方法,成员变量,方法参数之前,解释说明。

注解作用:(1)编写文档(2)代码分析(3)编译检查

15、对于Java中String类的理解

String是final类,不可被继承,成员方法都是final方法。

在源代码里通过char[]保存字符串

String一旦创建便不可修改,所有的操作都会新建对象

16、对于Java中字符串常量池的理解

为了提高性能,减少内存开销,在创建字符串常量时候会先检查字符串常量池当中是否存在该字符串,若有则直接返回该实例的引用,若没有则新建并保存在常量池当中。

字符串常量池分两种:

(1)静态常量池:.class文件常量池,保存有字符串字面量,类,方法的信息,占用class文件的大部分空间

(2)动态常量池:常量保存在内存当中,存储在方法区里,也叫运行时常量池。

17、Java中String类为何设计成不可变

这是综合内存,同步,数据结构和安全性等多方面的考虑。

(1)首先是字符串常量池的需要,String不可变可以避免出现脏数据。

(2)String可以缓存hashcode,这样不必计算hashcode,缓存是安全的。

(3)String作为很多类库的参数,不可变可以避免受到网络连接,文件操作等影响其安全性。

18、Java中Hash码的理解

Hashcode代表了对象的一种特征。

(1)Object类的hashcode返回的对象的内存地址转换后的值,因为每个对象的内存地址都不同,所以hashcode都不同

(2)String类的hashcode,只要字符串相等,hashcode就相等

(3)integer的hashcode返回的是对象里边的整数值

19、Object类的equals和hashcode方法的重写

(1)若两个对象equals比较相等,则hashcode一定相等

(2)若两个对象的hashcode比较相等,则equals比较不一定相等,因为hashcode方法可以重载,若不重载,两个对象的hashcode一定不同

20、Java常用集合List,Set,Map的区别

Set是最简单的集合,内部元素无序且不重复

(1)TreeSet:实现了SortedSet接口,能够对集合当中的元素进行排序

(2)HashSet:基于哈希算法存取数据的集合,速度快。

LIst是采用线性方式存储数据

(1)ArrayList:可变长度数组,可以访问数组当中的任意元素,插入删除速度较慢。

(2)LinkedList:采用链表数据结构的数组,插入删除速度快,查询速度稍慢。

Map映射是关键字对象映射的集合

(1)HashMap基于散列表的实现,插入查询的键值对开销固定

(2)LinkedHashMap使用链表的数据结构维护内部次序,迭代遍历时候比hashmap慢一点,但是在迭代访问时候比hashmap快

(3)TreeMap基于红黑树的数据结构实现。

21、ArrayMap和HashMap的区别

ArrayMap比HashMap慢,因为其采用二分法查找数据,插入删除数据时候重新调整空间,典型的牺牲时间换空间。

就存储结构而言,HaspMap采用HashMapEntry<Key,Value>[]存储数据,而ArrayMap是一个<Key,Value>数据结构,内部采用两个数组,一个记录key的hashcode,一个记录value值。

在数组扩容时候,HashMap会重新创建新对象,内存消耗大,而ArrayMap会采用copy数据的形式扩容。

ArrayMap是可收缩数组,在进行clear或者remove方法之后会释放内存空间。

22、HashMap和HashTable的区别

两者都是基于哈希表的实现,每个元素都是一个键值对。内部通过单链表解决冲突,容量不足时候会自动扩容。

HashMap是线程不安全的,适用于单线程环境,HashTable是线程安全的。

两者都实现了序列化接口,都可以被克隆。

元素不可以包含重复的key,但是可以包含重复的value

HashTable的key和value都不能为null

HashMap的key可以为null,但是仅有一个,可以有多个键对应的值为null。

23、HashMap和HashSet的区别

HashMap实现了Map接口,存储键值对,通过put方法存储数据,通过key计算hashcode,取对象快,因为使用唯一的键获取对象。

HashSet实现了Set接口,存储对象,使用add方法添加元素,使用成员对象计算hashcode,在速度上没有HashMap快。

24、ArrayList和LinkedList的区别

ArrayList和LinkedList都实现了List接口,ArrayList是动态数组的数据结构,LinkedList是链表的数据结构,在随机访问时候,ArrayList速度比较快,因为LInkedList是采用移动指针查找数据,指针从前往后查找浪费时间。在进行删除插入时候LinkedList速度比较快,因为ArrayList会对操作点之后的所有数据进行下标索引的修改,并移动数据。

25、数组和链表的区别

数组当中元素在内存当中连续存储,占用连续的内存空间,随机访问效率高,但是需要提前申请内存地址,编译时候确定空间大小,不可动态改变,数据多了会溢出,数据少了会浪费内存空间。

链表可以动态的申请内存,插入删除数据灵活,但是随即访问效率不高。

26、Java中多线程实现的三种方式

(1)继承自Thread类,实现Runnable接口,调用start方法开启新线程,并执行run方法。

(2)创建Thread类的实例化对象,传入实现的Runnable接口,当Thread类接收到Runnable target的参数之后,Thread的run方法会调用target.run()

(3)使用ExecutorService,Callable,FutureTask实现有返回结果的多线程,如果要获取返回值,必须实现Callable接口。执行Callable任务后,得到FutureTask对象,通过对象的get方法获取返回的结果对象,结合线程池ExecutorService可以实现有返回结果的多线程。

27、Java中run()和start()的区别

start方法是开启新的线程,并执行其中的run方法,而run是在当前线程执行,并不会开启新线程。

28、如何控制某个方法允许并发访问线程数的方法

通过信号量对象Semaphore来控制允许并发访问线程数

Semaphore se = new Semaphore(5,true)申请五个信号量

当任务执行过程中,调用对象的acquire()方法请求一个信号量,此时信号量总数减一,释放时候调用release(),信号量加一,当信号量为0时候则会阻塞线程。

29、Java中wait和sleep方法的不同

sleep方法属于Thread类,会让程序暂停指定的时间,释放CPU资源,而不会释放锁,当倒计时结束时候,会自动开始运行。

wait方法属于Object类,该方法会释放锁,并进入到等待锁定池,只有当调用对象的notify方法时候线程才会重新获取锁并开始运行。

30、对于Java中wait和notify关键字的理解

wait,notify,notifyAll都是Object类的方法

当程序调用wait方法,会释放锁,进入到等待锁定区。

调用notify方法会通知线程获取锁,重新开始运行

notifyAll会通知所有等待该对象的线程开始运行,但是具体唤醒哪一个取决于系统。

31、什么是线程阻塞,线程如何关闭

程序会一直等待该方法的完成,在此期间不做任何事情。

如何关闭:

(1)调用线程的interrupt方法(stop方法已经不推荐)

(2)使用标志位终止线程

32、如何保证线程的安全

(1)使用Synchronized关键字修饰

(2)使用Object类的wait和notify方法协作。

(3)使用ThreadLocal实现

33、实现线程同步的方式

(1)使用Synchronized关键字修饰方法或者语句块

(2)使用特殊域变量volatile实现线程同步

34、Java中synchronized关键字的用法,以及内置锁,对象锁,类锁的区别

Synchronized修改方法或者代码块。

Java类内部有一个用来实现同步的锁,叫做内置锁。当线程进入同步方法或者代码块时候,自动获得该同步锁,退出时候自动释放该内置锁。内置锁是个互斥锁,当线程B访问线程A持有的内置锁的时候,会进入等待状态或者阻塞,直到线程A释放该锁。

对象锁用于类的实例方法或者对象,类锁用于类的class对象或者静态方法。因为一个类可以有多个实例对象,所以可以有多个对象锁,对象锁之间互不干扰,而只有一个Class对象,所以只有一个类锁。

35、Java中锁和同步的知识

锁有两种特性:互斥和可见。

互斥性:线程A持有该锁的时候是不允许其他线程访问的

可见性:线程A在持有锁期间对于对象的操作,在其他线程取得该锁之后是可见的。

同步:

使用Synchronized关键字,使用锁对象

使用volatile,在变量的值发生改变的时候及时通知其他线程。

36、synchronized和volatile的区别理解

Synchronized是锁定当前变量,不允许其他线程访问。

Volatile是告诉JVM当前寄存器当中的值是不确定的,需要从主存当中读取。

Synchronized可以修饰类,变量,方法,Volatile只能用来修饰变量

Synchronized具有可见性和原子性,而Volatile只具有可见性。

Synchronized会阻塞线程,而Volatile不会阻塞线程。

Synchronized对于变量的标记可以被编译器优化,而Volatile对于变量的标记不会被优化。

37、Java中原子性,可见性,有序性的理解

原子性,也叫作不可分割性,比如a=0是不可能分割的,所有具有原子性,而a++则不具有原子性,因为等于a=a+1,是可以被分割的。非原子性的操作一般都存在线程安全的问题,所以可以通过synchronized使其变为原子操作。

可见性:一个线程对于对象的修改对于另外要操作该对象的线程是可见的。

有序性:线程的执行顺序也就是代码的先后顺序。

38、ReentrantLock,Synchronized,Volatile关键字的理解

ReentrantLock可重入锁,类似于同步锁,但是他必须显性的创建和销毁。

(1)ReentrantLock具有tryLock方法,如果锁被其他线程持有,会返回false,避免死锁。

(2)创建的时候是可以被定义为可以被抢占的。

(3)ReentrantReedWriteLock用于读多写少的情况,不存在互斥的场景,提高性能。

Synchronized是互斥锁,锁被当前线程持有的话是不允许其他线程访问的,必须等到当前线程释放该锁。

Volatile保证变量对于所有线程是可见的,他会强制将缓存的修改写入到主存当中,当他操作之后,其他CPU的缓存都是无效的

39、Java中死锁概念,它产生的四个必要条件

死锁:多个线程都在等待资源的释放,但是又都处于无限期的等待当中,导致程序不能正常运行。

死锁的四条件:

(1)互斥:一个资源只能被一个线程访问,当其他线程访问时候进入等待状态

(2)请求与保持:线程的执行需要请求其他的资源,但是所需的资源被其他线程持有,则进入等待状态,但是又不释放自己所持有的资源。

(3)不可被剥夺:当前线程持有的资源是不能被其他的线程强制剥夺的。

(4)循环等待:多个线程请求资源,形成收尾相连的循环等待状态。

避免死锁:系统对于他可以满足的资源请求进行动态检查,如果分配该资源后可能造成死锁,则不分配该资源。

40、Java中堆和栈的理解

Java中内存分为两种:堆内存、栈内存

堆内存存储对象和数组,先进先出,后进后出,动态分配内存大小,存取速度慢

栈内存:程序执行用,先进后出,后进先出,存取速度快,仅次于寄存器,栈数据可以共享,但是栈中数据大小,生存周期都是固定的。

41、理解线程间通信

安卓当中子线程进行耗时操作,主线程用来更新UI和相应用户操作。线程之间的通信通过Handler来进行处理,handler通过sendMessage方法将包装好的Message消息发送到MessageQueue当中,Looper对象调用loop方法循环从MessageQueue当中读取消息,并交由主线程的handler进行处理

42、线程中join()方法理解,如何让多个线程顺序执行

Thread类的Join方法可以使两个并行执行的线程转换成串行执行,在线程B当中调用线程A的join方法,线程B会在线程A执行完成之后继续执行。如果在线程B当中调用线程A的join(1000)方法,表示A执行1000毫秒之后执行线程B。

多个线程顺序执行:在一个线程当中依次调用另外一个线程的join方法。

43、工作者线程和主线程的理解

主线程(UI线程)肩负着更新UI,相应用户操作的重任,耗时任务可以交给工作者线程,也就是子线程进行处理。

工作者线程:AsyncTask,IntentService,HandlerThread

这三个工作者线程本质上都是对于线程,线程池的封装。

44、AsyncTask的工作原理

AsyncTask是基于Handler和线程池的封装,使用它可以更新UI,其本质还是内部的handler将消息发送给主线程,主线程接受消息进行更新,其内部还有个线程池,可以避免不必要的线程创建和销毁的开销。

45、并发和并行的区别理解

并发:在单核机器上,CPU通过时间分片,快速的在多个任务之间进行切换执行,模拟出来多线程执行的假象,这种叫做并发。

并行:在多核机器上,CPU是真的同是进行多个任务的执行,具体可以同时执行多少个进行,取决于CPU的核数。

46、同步、异步,阻塞、非阻塞的区别理解

同步:一个服务的完成需要依赖另外一个服务,被依赖的服务完成之后,依赖该服务的服务才算完成,这是一种可靠的服务序列。

异步:一个服务的完成需要依赖另外一个服务,通知所依赖的服务开始执行之后,该服务就算完成,而不必关心所依赖的服务是否真的完成,这是一种不可靠的服务序列。

阻塞:在函数返回结果之前,线程一直被挂起,处于等待状态,直到结果返回才继续执行。

非阻塞:在不能立即得到返回结果之前,函数立即返回,不会阻塞线程。

同步非阻塞:当前服务在等待函数返回结果的时候,同时可以处理其他消息。

同步阻塞:当前服务在等待函数返回结果的时候,不处理任何事物,处于挂起状态

异步非阻塞:当前函数已经得到了返回结果,同时也在处理其他消息

异步阻塞:当前函数已经得到了返回结果,但是不处理其他消息,处于挂起状态

同步和异步的重点在于是否已经得到了返回结果。

阻塞和非阻塞的重点在当前线程在等待函数的返回结果的时候,是否处理其他消息。

47、Java中任务调度的理解

大部分操作系统的任务调度方式都是时间片轮转的抢占式的调度方式,也就是CPU以极快的速度在不同的任务之间来回切换,每个任务执行一段时间后就被强制切换到另外的任务接着执行,任务执行的这段时间就是时间片,等待任务执行的状态叫做就绪状态,任务执行时候的状态叫做运行状态,这种看似多任务同时执行的方式叫做并发。

48、Java中进程的详细概念

计算机的核心是CPU,操作系统是计算机的管理者,主要负责资源任务的分配和调度。应用程序是具有某种功能的程序,运行在操作系统上,进程是具有一个独立功能的程序在数据集上的一次动态执行的过程。进程是CPU分配资源的最小单位,是应用程序的载体,各个进程之间的内存地址相互隔离。

49、线程的详细概念

线程是程序执行当中一个单一的顺序控制流程,是程序执行流的最小单元。是CPU调度的最小单位,一个进程可以有多个线程,这多个线程共享它归属的进程的空间地址和资源,每个线程都有独立的栈内存存储本地数据,线程的上下文切换比进程快得多。

50、Android性能优化相关

(1)布局优化:较少页面的布局层次,重用布局,使用布局预加载(当布局需要时候的时候才加载)

(2)绘制优化:不在ondraw方法里边新建对象,进行耗时操作,因为渲染过程中ondraw方法会被不断地调用。

(3)使用线程池管理线程,控制线程的合理并发数,避免创建大量的线程类,造成资源抢夺,线程阻塞。

如何优化内存:

51、内存泄漏原因

内存泄漏:一个无用的对象仍然被其他的对象持有它的引用,导致这个无用对象的内存无法被释放。

原因:

(1)单例模式:单例模式的静态特性使得他的生命周期和程序的声明周期一样长,单例持有的对象的引用在整个应用程序运行期间都无法得到释放。

(2)静态变量:静态变量存储在方法区中,他的生命周期从类加载开始,一直到进程结束,他持有的对象的引用在这个周期只能都无法被释放。

(3)非静态内部类:内部类默认持有外部类的对象,如果内部类的生命周期比外部类对象生命周期长,则会导致内存泄漏,避免方式:静态内部类+弱引用

(4)未取消注册或者回调导致内存泄漏:如果在Activity中注册了广播,但是在页面销毁时候没有取消注册,那么广播会一直存在于系统当中,并持有Activity的引用。

52、通过Handler在线程间通信的原理

Android中主线程不能进行耗时操作,子线程不能更新ui,所以此时需要handler来进行线程间的通信。

Handler将包装好的Message信息通过sendMessage方法发送到MessageQueue当中,此时Looper对象通过loop方法循环从MessageQueue当中读取Message,并交给Handler处理,实现线程间的通信

53、Android中动画类型

帧动画:将多张图片按照指定的顺序和时间进行切换,形成动画效果。

补间动画:定时视图开始状态,变化方式,时间,通过算法进行一系列的变化实现动画效果,包括Alpha,Scale,Translate,Rotate。

属性动画:真实的改变view的属性,通过不断地重绘实现动画效果。

54、理解Activity,Window,View之间关系

Activity创建时候会初始化一个Window,就是PhoneWindow,PhoneWindow的根布局就是一个view或者viewgroup,

然后这个根布局通过addview方法在页面上添加视图控件。视图控件相应用户的交互操作通过windowManagerService来传递消息给Activity,并调用Activity的onClickListener等函数

55、Android中context详解

context是一个抽象基类,负责activity,intent,service,package,资源和权限操作

context分为三个层次:

(1)context抽象类

(2)ContextImpl,这个类包含有一个packageInfo,这个类包含包的所有信息。ContextWrapper是ContextImpl的封装,内部有一个ContextImpl的实例,可以调用ContextImpl的所有方法。

(3)Service,Application直接继承自ContextWrapper类,但是Activity需要一个主题,所以引入了一个contextThemeImpl类。

使用:在使用context创建静态变量,静态方法时候,要是用生命周期比较长的application的context,创建Activity页面内的view或者dialog时候可以用Activity的context

56、Java中double和float类型区别

float是单精度类型,取值范围在10的-38次方到10的38次方,使用四个字节保存数据

double是双精度类型,取值范围在10的-308次方到10的308次方,使用8个字节保存数据,

所有的声明默认都是double类型,要是用float类型则需要在数值后边添加f

57、Android存储数据的方式

(1)SharedPreference,使用xml文件存储简单的键值对数据

(2)本地文件存储,使用context的FileInputStream.openFileInput(String name)和FileOutputStream.openFileOutput(String

name , int mode)来操作文件的IO流。

(3)SQLite轻量级的嵌入式数据库引擎,支持SQL语言

(4)网络存储:通过网络进行数据的存储和读取

(5)ContentProvider存储数据

58、ANR了解以及优化

Application Not Responsing,应用程序无响应,当操作在一段时间内无法得到系统的相应时候便会出现ANR异常,主要原因在于线程任务在规定的时间内无法完成。

避免在主线程中进行耗时操作,使用子线程进行耗时操作,处理完成通过handler通知主线程更新UI

59、垃圾回收机制以及System.gc()理解

垃圾回收:对于堆内存当中的对象进行识别,如果对象被引用,则成为存活对象,如果对象没有被引用,则称为垃圾对象,可以被回收。

JVM进行gc的频率很高,因为这种GC用时很短,对于系统没有太大影响,但是主GC对于系统的影响比较明显,所以进行主GC需要满足一定的条件

(1)没有任何应用线程活动的时候,才会调用主GC,因为主GC在优先级最低的线程中。

(2)当堆内存不足时候,会调用主GC,应用程序运行中,创建新对象申请内存空间满足不了时候,便会调用主GC,如果内存回收之后仍然无法满足,责任连续两次调用,如果仍然无法满足,则会报OOM

System.gc()只会提醒jvm进行内存回收,但是具体什么时间回收还是取决于jvm。

60、Android平台优势和不足

优势:

(1)开放性:开放性使其拥有更多的移动终端厂商,和更多的开发者。

(2)丰富的硬件选择:开放性使得厂商可以为用户提供更多种类和功能的手机,满足用户的多样化的需求。

(3)摆脱运营商的限制:过去手机使用什么功能,接入什么网络大多受制于网络运营商,而安卓用户可以更加方便的接入网络,摆脱运营商限制。

不足:

(1)安全和隐私:系统的开放性使得其更加容易被找到系统安全和隐私方面的漏洞被攻破和传播。

(2)因为手机厂商众多,所以小众手机品牌遇到问题之后很难得到快速的服务。而且因为厂商的不同标准导致开发者进行应用开发和适配时候遇到更多问题。

61、Activity组件

Activity有三种状态:

(1)激活状态:页面处于最上层,获取了焦点,可以处理用户的操作和输入。

(2)暂停状态:页面被部分遮挡,失去焦点,例如被半透明的Dialog。

(3)停止状态:页面被其他的页面完全遮挡不可加,此时页面仍存在于内存之中,但是当内存不足时候可能会被回收,当再次被打开之后需要重新创建。

Activity生命周期:

(1)onCreate:页面被创建时候调用

(2)onStart:页面被创建之后,将对用户可见时候调用。

(3)onResume:页面处于最前端,对用户可见时候调用

(4)onPause:页面被其他页面遮挡,Activity退到后台时候调用

(5)onStop:页面停止活动,不再对用户可见时候调用。

(6)onDestory:页面销毁时候调用。

(7)onRestart:页面停止活动,再次活动之前调用。

Activity的启动方式:

(1)standard:默认的启动方式,每次都创建一个实例。

(2)singleTop:如果栈顶有实例,则不新建,如果没有则新建。

(3)singleTask:如果栈里有实例,则关闭这个实例上边的所有实例,关闭顺序和打开顺序一样

(4)singleInstance:使用单独的一个栈保存实例

62、Service组件

Service主要用来处理不干扰用户的后台操作,诸如应用更新,播放音乐。Service不开启新的线程,运行在主线程之中,所以这要求Service不能阻塞应用,不然会ANR。

Service启动方式:

(1)startService启动后运行在后台,不需要用户操作的情况下实现某种功能。

(2)bindService开启服务,启动着和服务者之间建立绑定关系,应用程序可以和Service组件进行交互。

startService:如果要开启的服务已经存在,则调用onStartCommant,否则的话新建Service,启动后的Service会一直运行在后台,除非调用stopService或者stopSelf

bindService:如果目标Service已经存在,则与之绑定,若没有则新建Service并与之绑定,这样启动的Service运行状态受到与他绑定的对象的影响。

63、BroadcastReceiver组件

广播是安卓系统的通信机制,系统发送的广播叫做系统广播,应用程序发送的广播叫做自定义广播,广播实际是Intent对象,接受广播也就是接受Intent对象。

接受广播需要自定义广播接收器,继承自BroadcastReceiver,该对象执行完onReceiver方法之后会自行销毁,所以不能在onReceiver方法中进行耗时操作或者开启子线程,父线程关闭后,子线程也要关闭,导致线程不安全。

发送广播的两种类型:

(1)无序广播:sendBroadcast(),它是异步的,所有的接收器的执行顺序不确定,这种效率更高,但是BroadcastReceiver无法使用setResult,getResult,abortBroadcast方法,广播不能被终止,数据不能被修改。

(2)有序广播:sendOrderedBroadcast(),从优先级最高的广播接收器开始接收,如果接收完了没有被丢弃,就传给下一个优先级的接收器,直到最后。广播可以被终止,数据传输过程中可以被修改。

注册广播接收器两种方法:

(1)静态注册:在清单文件中,写在application的标签内部,使用receiver标签。这种广播不受生命周期影响,属于常驻型广播,消耗CPU资源

(2)动态注册:在代码中使用registerReceiver方法注册,使用这种方法注册的广播必须有对应的解除注册,使用unregisterReceiver()

64、ContentProvider组件

安卓系统将所有的数据都规定为私有数据,当程序要访问其他程序的数据或者给其他程序提供数据时候,需要使用ContentProvider,他对数据进行了统一的封装处理,不必关心数据的存储方式。

URI(统一资源标识符)分为三个部分:

(1)访问协议

(2)统一标识字符串

(3)数据资源

使用方法:继承自ContentProvider,并实现其中的方法,然后在配置文件中通过标签进行注册,主要有三个标签

(1)name定义ContentProvider的全路径

(2)authories为访问标识

(3)exported为是否允许外部程序访问

在另一个需要操作该程序提供的数据的应用当中,通过context.getContentResolver方法获取ContentResolver对象,并使用其中方法操作数据。

64、什么是Armv7?
安卓中有七种CPU架构,Armv7是最常见的,他针对电池进行了优化。

其中CPU架构:Armeabi,Armeabi-v7a,Arm64-v8a,x86,x86_64,mips,mips64

65、为什么字节码不能在Android中运行

因为Android运行的是DVM虚拟机(Dalvik虚拟机),而不是JVM虚拟机。

66、Gradle中的BuildType是什么?你一般用它来干什么

BuildType定义了Gradle在构建和打包apk时使用的属性。

一般可以这样用:

(1)BuildType定义了如何构建模块,例如是否运行ProGuard。

(2)构建中包含哪些资源可以用到BuildType

(3)Gradle为项目的不同风格和产品功能组合创建一个构建变体

67、简述一下安卓的构建过程

(1)使用aapt工具编译资源文件夹/res,将其编译为一个R.java的类文件

(2)通过javac将Java源代码编译成.class文件,然后通过sdk工具中的dx工具将其转换成成DVM字节码,输出为classes.dex

(3)通过Android Apk Builder将所有的输入构建成APK文件

68、说明下onCreate()和onStart()区别

onCreate()方法在页面新建时候调用,onStart()在Activity页面对于用户可见也就是onCreate()或者onRestart()方法之后,都会调用onStart()

69、为什么在onCreate()方法中执行setContentView

setContentView是一项繁重的操作,而且onCreate方法只会在页面创建时候调用一次,而onResume或者onStart方法都会可能多次调用,所以要在onCreate方法中调用。

70、如何在旋转屏幕时候防止数据重新加载

使用ViewModel和onSaveInstanceState,ViewModel具有LifeCycle-Aware功能,它的所有者因为配置更改而销毁,但是ViewModel不会销毁,所以它的所有者的新实例可以重新连接到现有的ViewModel。所以通常会将数据存储到ViewModel当中,而onSaveInstanceState仅仅会保存少量UI数据。

71、SharedPreference的commint和apply方法的区别

commint是同步的,调用之后会立即返回boolean值的处理结果。

apply是异步的,不会返回处理结果布尔值。

72、Fragment生命周期

onAttach:将Fragment和Activity产生关联时候调用

onCreate:Fragment被创建时候调用

onCreateView:创建并返回与Fragment相关的布局界面

onViewCreated:在onCreateView之后立即调用

onActivityCreated:通知Fragment它所关联的Activity已经完成了onCreate方法的调用

onStart:让Fragment准备与用户可见,与相关连的Activity的onStart方法关联

onResume:对用户可见,可以相应用户操作,和Activity的onResume关联

onPause:用户离开Fragment时候调用,可能由于关联的Activity被遮挡或者同一个Activity当中的其他Fragment操作引起的

onStop:Fragment不可见时候调用,可能由于关联的Activity不可见或者其他Fragment的操作引起

onDestroyView:Fragment清理和他相关的view资源

onDestroy:最终清理Fragment的状态

onDetach:Fragment和Activity不再关联

73、安卓事件分发机制

用户操作屏幕产生的Touch事件被封装成MotionEvent对象,然后通过dispatchTouchEvent方法进行事件分发,在onInterceptTouchEvent方法当中进行拦截处理,最后交由onTouchEvent进行最终的事件处理。

74、Bitmap的使用和内存优化

BitmapFactory是创建Bitmap的工具类,可以以文件、字节数组、输入流的方式创建图像。BitmapFactory提供的都是静态方法,BitmapFactory.Options类使BitmapFactory的静态内部类。

将大尺寸图片解析为控件需要的尺寸思路:

实例化BitmapFactory . Options对象来获取解析属性对象,设置BitmapFactory. Options的属性inJustDecodeBounds为true后,再解析位图时并不分配存储空间,但可以计算出原始图片的宽度和高度,即outWidth和outHeight,将这两个数值与控件的宽高尺寸相除,就可以得到缩放比例,即inSampleSize的值,然后重新设置inJustDecodeBounds为false,inSampleSize为计算所得的缩放比例,重新解析位图文件,即可得到原图的缩略图。

75、MVC,MVP,MVVM的区别

MVC是 Model-View-Controller 体系结构,其中模型是指数据模型类。该视图引用xml文件,并且控制器处理业务逻辑。这种体系结构的问题是单元测试。该模型不受任何约束,因此可以轻松测试。控制器与android api紧密耦合,因此很难进行单元测试。由于视图和控制器紧密耦合,因此模块化和灵活性是一个问题。如果我们更改视图,则控制器逻辑也应更改。维护也是一个问题。

MVP是Model-View-Presenter体系结构,该视图包括xml和Activity/Fragment类。因此,该活动理想情况下将实现一个视图界面,​​从而使单元测试更加容易(因为这将在没有视图的情况下起作用)

MVVM是 Model-View-ViewModel 体系结构。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。当然这些事 ViewModel 已经帮我们做了,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。

MVVM优点:

  • 低耦合:一个ViewModel可以绑定到多个View视图上,两者当中的一方有变化时候可以不影响另一方
  • 可重用性:视图逻辑可以放到ViewModel中,多个View可以复用这个视图逻辑
  • 可测试:现在测试可以基于ViewModel来进行编写
  • 独立开发:开发人员专注于业务逻辑和数据的开发ViewModel,设计人员专注于设计界面

76、Glide相关问题

Glide的缓存设计可以说是非常先进的,考虑的使用场景也很全面。Glide缓存可以分为内存缓存和磁盘缓存。其中内存缓存又分为Lru算法缓存、弱引用缓存。

Glide加载图片读取的顺序是:Lru算法缓存、弱引用缓存、磁盘缓存。写入的顺序是:弱引用缓存、Lru算法缓存、磁盘缓存。

Glide三级缓存流程:应用加载某张图片时候,先从LruCache当中读取,有的话直接取出,没有的话接着从WeekReference当中读取,如果读取到的话则拿来使用,同时将图片再次放入LruCache当中,如果没有的话则去磁盘当中读取,如果有的话拿来使用,并缓存到LruCache当中,如果没有则通过网络将图片下载下来,保存到磁盘当中,并缓存到LruCache中。

LruCache算法:Least Recently Used,又称为近期最少使用算法。原理就是把近期使用的对象的强引用存储到LinkHashMap上,并把最近最少使用的对象在缓存池达到预设值之前从内存当中移除。

Glide加载大图:Glide不会将整个原图加载到内存当中,而是用多少加载多少,Glide会根据ImageView的尺寸大小,缓存合适的尺寸的图片进行展示。而Picasso则是会将整个原图加载到内存当中。如果一个页面是200x200尺寸,一个页面是100x100尺寸,那么Glide缓存两张对应ImageView尺寸的图片。

Glide加载图片质量默认使用RGB_565,Picasso加载图片质量默认使用ARGB_8888。

Glide和Fresco比较(两者都支持gif图片展示):

(1)Fresco宣称的不占用内存实际上在高版本的安卓系统上还是会使用java内存,不可避免的。

(2)Fresco支持的最大显示图片为2M,对于大图片,Glide正常显示,但是Fresco会显示黑屏。

(3)Fresco推荐使用他自己的SimpleDraweeView 来显示图片,有些不友好。

(4)Fresco更多的native的实现,所以需要对于NDK比较了解,使用遇到问题之后,修改的成本略高。

(5)Glide可以使用BitmapTransformation来定义更多形状的图片展示。

77、TCP链接的三次握手,四次挥手

Android面试Java问题整理相关推荐

  1. 【Android 面试基础知识点整理】

    针对Android面试中常见的一些知识点整理,Max 仅仅是个搬运工.感谢本文中引用文章的各位作者,给大家分享了这么多优秀文章.对于当中的解析,是原作者个人见解,有错误和不准确的地方,也请大家积极指正 ...

  2. Android面试复习资料整理

    Activity巩固和复习 1. 什么是Activity 四大组件之一,通常一个用户交互界面对应一个activity.activity是Context的子类,同时实现了window.callback和 ...

  3. android智能!46道面试题带你了解中高级Android面试,吐血整理

    前言 大家应该看过不少人分享的面试成功的面经,是不是觉得自己"说不定也可以"呢? 这里重提一个理论:幸存者偏差.当取得资讯的渠道,仅来自于幸存者时(因为死人不会说话),此资讯可能会 ...

  4. 我自己的Android面试试题总结整理

    http://blog.sina.com.cn/s/blog_ad991b1601018mjc.html 2013-5-9号补充:今天最新的腾讯面试题,应该说是所有面试中最难的,我个人感觉.而且是个女 ...

  5. 【Android -- 面试】精心整理 Android 面试题(2022求职必看)

    前言 如今,Android 开发岗的就业形势逐渐严峻,不像前几年那么热门,但是高级人才依然紧缺.想要在众多面试者中脱颖而出,拿下大厂 offer,就必须全面梳理知识点,扩充题库,并针对面试中可能遇到的 ...

  6. 2021年国内一线互联网大厂内部题库Android面试(Java篇)

    9.进程和线程的区别(猎豹) 简而言之,一个程序至少有一个进程,一个进程至少有一个线程. 线程的划分尺度小于进程,使得多线程程序的并发性高. 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内 ...

  7. Android面试:整理了Android面试官最常问的174道面试题,让你秒变offer收割机

    本文是专为 Android 开发工程师准备的高薪面试真题汇总题库,涵盖历年大厂高频面试题总结+核心考点深度解析,可以帮助大家全面梳理知识点,并针对面试中可能遇到的问题进行深入分析,在众多面试者中脱颖而 ...

  8. 一个BAT大厂面试者整理的Android面试题目!

    身边好多朋友都裸辞了,出去旅游了一圈之后,回来才发现,工作并没有想象中那么好找.朋友小A一心只想进大厂面试Android,于是面试了阿里巴巴.美团.滴滴等,最后在某个大厂经历了5轮面试后拿到了offe ...

  9. Android 笔试/面试,常见问题整理

    Android 笔试/面试,常见问题整理 Android学习书籍下载的网址:http://pan.baidu.com/s/1slCSUcP 上面网盘里面的书籍都是PDF格式的,有面试宝典,疯狂java ...

最新文章

  1. c语言 程序 注入,远程线程注入 c语言实现
  2. linux配置apache文件大小,linux下apache中httpd.conf文件配置参数说明
  3. python装饰器补充
  4. 基于matlab 的燃油喷雾图像处理方法,基于MATLAB的燃油喷雾图像处理方法.doc
  5. QC使用流程(1)之安装篇
  6. 域名授权系统源码 网站源码授权系统_单域名授权系统
  7. openstack用户列表_什么是OpenStack超级用户?
  8. SQLite Tutorial 2 install free sqlite gui manager in firefox
  9. MongoDb系列文章
  10. 再谈研发那些事——两项核心工作的区别与联系
  11. 提高智商、改善记忆力的120种绝佳方法!
  12. idea使用教程-idea简介
  13. 关于用WinHex解析vm虚拟机的.vmdk文件。
  14. 伽卡他卡使用教程_伽卡他卡电子教室安装使用和常见问题
  15. mysql弱口令字典_自制弱口令字典top100
  16. 木马是如何穿过防火墙的
  17. linux中 777,755等用户权限说明
  18. 智能养殖畜牧系统研发
  19. 父类引用和子类引用之间 的关系
  20. 【附源码】计算机毕业设计JAVA九宫格日志网站

热门文章

  1. 用python做词云 包含:处理词云形状+分词+绘制词云
  2. 标准c语言程序设计答案,C语言程序设计标准答案.doc
  3. VC6.0 realease下编译错误
  4. React-Native打包(Realease)出现unable to process incoming event 'ProcessComplete' (ProgressCompleteEvent)
  5. 2018再见了啊!!!2019继续努力!新年快乐~!!!
  6. Qt报错 The process was ended forcefully. (程序异常结束)
  7. opencv报错LNK2019
  8. c语言电梯调度算法源代码,电梯调度算法(源代码)
  9. c语言结构体结构体变量名,C语言结构体及结构体变量
  10. 构建wordpress集群