android面试题解答

@ android面试题解答

1.Android的四大组件是哪些,它们的作用?

Activity:Activity是Android程序与用户交互的窗口,是Android构造块中最基本的一种,它需要为保持各界面的状态,做很多持久化的事情,妥善管理生命周期以及一些跳转逻辑

service:后台服务于Activity,封装有一个完整的功能逻辑实现,接受上层指令,完成相关的事物,定义好需要接受的Intent提供同步和异步的接口

Content Provider:是Android提供的第三方应用数据的访问方案,可以派生Content Provider类,对外提供数据,可以像数据库一样进行选择排序,屏蔽内部数据的存储细节,向外提供统一的借口模型,大大简化上层应用,对数据的整合提供了更方便的途径

BroadCast Receiver:接受一种或者多种Intent作触发事件,接受相关消息,做一些简单处理,转换成一条Notification,统一了Android的事件广播模型

2.Android基本布局

常用五种布局方式,分别是:FrameLayout(框架布局),LinearLayout (线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局)。

一、FrameLayout:所有东西依次都放在左上角,会重叠,这个布局比较简单,也只能放一点比较简单的东西。二、LinearLayout:线性布局,每一个LinearLayout里面又可分为垂直布局(android:orientation=“vertical”)和水平布局(android:orientation=“horizontal” )。当垂直布局时,每一行就只有一个元素,多个元素依次垂直往下;水平布局时,只有一行,每一个元素依次向右排列。三、AbsoluteLayout:绝对布局用X,Y坐标来指定元素的位置,这种布局方式也比较简单,但是在屏幕旋转时,往往会出问题,而且多个元素的时候,计算比较麻烦。四、RelativeLayout:相对布局可以理解为某一个元素为参照物,来定位的布局方式。主要属性有:相对于某一个元素android:layout_below、 android:layout_toLeftOf相对于父元素的地方android:layout_alignParentLeft、android:layout_alignParentRigh;五、TableLayout:表格布局,每一个TableLayout里面有表格行TableRow,TableRow里面可以具体定义每一个元素。每一个布局都有自己适合的方式,这五个布局元素可以相互嵌套应用,做出美观的界面。

3.android中的动画有哪几类,它们的特点和区别是什么

android中动画主要分成两类,属性动画和非属性动画,非属性动画分成补间动画和帧动画。
属性动画view的位置、方向、大小会真实的放生改变。非属性动画只是表面执行动画,属性并没有改变。

4. android 中有哪几种解析xml的类?官方推荐哪种?以及它们的原理和区别。

XML解析主要有三种方式,SAX、DOM、PULL。常规在PC上开发我们使用Dom相对轻松些,但一些性能敏感的数据库或手机上还是主要采用SAX方式,SAX读取是单向的,优点:不占内存空间、解析属性方便,但缺点就是对于套嵌多个分支来说处理不是很方便。而DOM方式会把整个XML文件加载到内存中去,这里Android开发网提醒大家该方法在查找方面可以和XPath很好的结合如果数据量不是很大推荐使用,而PULL常常用在J2ME对于节点处理比较好,类似SAX方式,同样很节省内存,在J2ME中我们经常使用的KXML库来解析。

5.ListView的优化方案

1、如果自定义适配器,那么在getView方法中要考虑方法传进来的参数contentView是否为null,如果为null就创建contentView并返回,如果不为null则直接使用。在这个方法中尽可能少创建view。

2、给contentView设置tag(setTag()),传入一个viewHolder对象,用于缓存要显示的数据,可以达到图像数据异步加载的效果。

6.请介绍下Android的数据存储方式。

使用SharedPreferences存储数据;文件存储数据;SQLite数据库存储数据;使用ContentProvider存储数据;网络存储数据;
Preference,File, SQLite这三种方式分别对应的目录是/data/data/Package Name/Shared_Pref, /data/data/Package Name/files, /data/data/Package Name/database 。

7.activity的启动模式有哪些?是什么含义?

在android里,有4种activity的启动模式,分别为:

“standard” (默认)

“singleTop”

“singleTask”

“singleInstance”

“standard”对于没一个启动Intent都会生成一个activity的新实例;

“singleTop”的activity如果在task的栈顶的话,则不生成新的该activity的实例,直接使用栈顶的实例,否则,生成该activity的实例。

比如现在task栈元素为A-B-C-D(D在栈顶),这时候给D发一个启动intent,如果D是 “standard”的,则生成D的一个新实例,栈变为A-B-C-D-D。

如果D是singleTop的话,则不会生产D的新实例,栈状态仍为A-B-C-D

如果这时候给B发Intent的话,B的launchMode是”standard” 或者 “singleTop” ,会生成B的新实例,栈状态变为A-B-C-D-B。如果launchMode是“singleTask”则会清除CD,栈状态成为A-B,如果launchMode是“singleInstance”,清除栈中所有实例,栈状态是B。

“singleTask”如果在栈顶,则接受intent,否则,该intent会被丢弃,但是该task仍会回到前台。
当已经存在的activity实例处理新的intent时候,会调用onNewIntent()方法

8 Intent Flag有哪些?其含义?

FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
FLAG_ACTIVITY_SINGLE_TOP

FLAG_ACTIVITY_NEW_TASK如果设置,这个Activity会成为历史stack中一个新Task的开始。

FLAG_ACTIVITY_CLEAR_TOP 如果设置,并且这个Activity已经在当前的Task中运行,因此,不再是重新启动一个这个Activity的实例,而是在这个Activity上方的所有Activity都将关闭,然后这个Intent会作为一个新的Intent投递到老的Activity(现在位于顶端)中。

例如,假设一个Task中包含这些Activity:A,B,C,D。如果D调用了startActivity(),并且包含一个指向Activity B的Intent,那么,C和D都将结束,然后B接收到这个Intent,因此,目前stack的状况是:A,B。

上例中正在运行的Activity B既可以在onNewIntent()中接收到这个新的Intent,也可以把自己关闭然后重新启动来接收这个Intent。如果它的启动模式声明为 “multiple”(默认值),并且你没有在这个Intent中设置FLAG_ACTIVITY_SINGLE_TOP标志,那么它将关闭然后重新创建;对于其它的启动模式,或者在这个Intent中设置FLAG_ACTIVITY_SINGLE_TOP标志,都将把这个Intent投递到当前这个实例的onNewIntent()中。

这个启动模式还可以与FLAG_ACTIVITY_NEW_TASK结合起来使用:用于启动一个Task中的根Activity,它会把那个Task中任何运行的实例带入前台,然后清除它直到根Activity。这非常有用,例如,当从Notification Manager处启动一个Activity。

9.请描述下Activity的生命周期。

activity的生命周期方法有:onCreate()、onStart()、onReStart()、onResume()、onPause()、onStop()、onDestory();

10.activity在屏幕旋转时的生命周期

不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次;设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次;设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

11.如何启用Service,如何停用Service。

需要通过调用Context.startService()或Context.bindService()方法启动服务。这两个方法都可以启动Service,但是它们的使用场合有所不同。使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止。

12.广播有几种方式,这些方式有何优缺点?

答:首先写一个类要继承BroadcastReceiver

第一种:在清单文件中声明,添加

<action android:name=“android.provider.Telephony.SMS_RECEIVED”)

第二种使用代码进行注册如:

IntentFilter filter = new IntentFilter(“android.provider.Telephony.SMS_RECEIVED”);

IncomingSMSReceiver receiver = new SMSReceiver();

registerReceiver(receiver.filter);

两种注册类型的区别是:

1)第一种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。

2)第二种不是常驻型,和当前activity的生命周期一样。

13.请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系。

答:简单的说,Handler获取当前线程中的looper对象,looper用来从存放Message的MessageQueue中取出Message,再有Handler进行Message的分发和处理.

Message Queue(消息队列):用来存放通过Handler发布的消息,通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列

Handler:可以发布或者处理一个消息或者操作一个Runnable,通过Handler发布消息,消息将只会发送到与它关联的消息队列,然也只能处理该消息队列中的消息

Looper:是Handler和消息队列之间通讯桥梁,程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的Handler,Handler接受到消息后调用handleMessage进行处理

Message:消息的类型,在Handler类中的handleMessage方法中得到单个的消息进行处理

14.Service和Thread的区别?

Service 是运行在主进程的 main 线程上的。
Thread 的运行是独立于 Activity 的,也就是说当一个 Activity 被 finish 之后,如果你没有主动停止 Thread 或者 Thread 里的 run 方法没有执行完毕的话,Thread 也会一直执行。因此这里会出现一个问题:当 Activity 被 finish 之后,你不再持有该 Thread 的引用。另一方面,你没有办法在不同的 Activity 中对同一 Thread 进行控制。
Service 是一种消息服务,你可以在任何有 Context 的地方调用 Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也可以在 Service 里注册 BroadcastReceiver,在其他地方通过发送 broadcast 来控制它,这些都是 Thread 做不到的。

15.IntentService有何优点?

Android 中的service是运行在主线程上的,如果运行态耗时的操作将会使整个Activity处于假死状态,无法进行别的操作。这时候就需要用到intentservice。

16.如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?

重写onSaveInstanceState()方法,在此方法中保存需要保存的数据,该方法将会在activity被回收之前调用。通过重写onRestoreInstanceState()方法可以从中提取保存好的数据

17. 如何退出Activity?如何安全退出已调用多个Activity的Application?

对于多个activity,1、记录打开的Activity:每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。2、发送特定广播:在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。3、递归退出:在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。为了编程方便,最好定义一个Activity基类,处理这些共通问题。

18.AIDL的全称是什么?如何工作?

Android Interface Define Language
设计AIDL这门语言的目的就是为了实现进程间通信。在Android系统中,每个进程都运行在一块独立的内存中,在其中完成自己的各项活动,与其他进程都分隔开来。可是有时候我们又有应用间进行互动的需求,比较传递数据或者任务委托等,AIDL就是为了满足这种需求而诞生的。通过AIDL,可以在一个进程中获取另一个进程的数据和调用其暴露出来的方法,从而满足进程间通信的需求
通常,暴露方法给其他应用进行调用的应用称为服务端,调用其他应用的方法的应用称为客户端,客户端通过绑定服务端的Service来进行交互。

19.http理解

客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line)、请求头部(header)、请求数据三个部分组成,

请求行包括:请求格式,请求url,请求协议等
请求头包括:
Accept :请求报文可通过一个“Accept”报文头属性告诉服务端 客户端接受什么类型的响应。
例如Accept:text/plain 说明客户端接收文本
Accept-Charset:接收的编码集
Cookie:客户信息
Referer表示这个请求是从哪个URL过来的
详情请看https://en.wikipedia.org/wiki/List_of_HTTP_header_fields
请求数据就是post传的参数

HTTP响应也由三个部分组成,分别是:状态行、消息报头、响应正文。

状态码就是请求返回的结果码:200代表成功,其余代表失败比如404
消息报头和请求头部一样
响应正文就是得到的数据。

http三次握手

在这里插入图片描述
第一次握手:主机A发送位码为syn=1,随机产生seq number=1234567的数据包到服务器,主机B由SYN=1知道,A要求建立联机;

第二次握手:主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),syn=1,ack=1,随机产生seq=7654321的包

第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则连接建立成功。

俩次握手行不行

如果俩次握手,主机A无法知道消息是不是由刚才连接的主机发过来的。容易受到中间商攻击。

http断开需要几次握手

四次挥手(断开连接)
第一次: TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。

第二次:服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。

第三次:服务器关闭客户端的连接,发送一个FIN给客户端。

第四次:客户端发回ACK报文确认,并将确认序号设置为收到序号加1。

https几次握手

在这里插入图片描述
在使用HTTPS是需要保证服务端配置正确了对应的安全证书

客户端发送请求到服务端

服务端返回公钥和证书到客户端

客户端接收后会验证证书的安全性,如果通过则会随机生成一个随机数,用公钥对其加密,发送到服务端

服务端接受到这个加密后的随机数后会用私钥对其解密得到真正的随机数,随后用这个随机数当做私钥对需要发送的数据进行对称加密

客户端在接收到加密后的数据使用私钥(即生成的随机值)对数据进行解密并且解析数据呈现结果给客户

SSL加密建立

20.MVC MVP MVVM原理和区别

21.List遍历方式,哪种方式最快

22.Retrofit实现原理

23.Java object对象有哪几种方法,作用是什么?

在Java中,只有基本类型(int,boolean等)的值不是对象。其他类型,包括数组类型,不管是对象数组还是基本类型的数组都扩展于Object类。

方法摘要
protected Object clone() 创建并返回此对象的一个副本。
boolean equals(Object obj) 指示某个其他对象是否与此对象“相等”。
protected void finalize() 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
Class<? extendsObject> getClass() 返回一个对象的运行时类。
int hashCode() 返回该对象的哈希码值。
void notify() 唤醒在此对象监视器上等待的单个线程。
void notifyAll() 唤醒在此对象监视器上等待的所有线程。
String toString() 返回该对象的字符串表示。
void wait() 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
void wait(long timeout) 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。
void wait(long timeout, int nanos) 导致当前的线程等待,直到其他线程调用此对象的 notify()

24.设计模式有哪些?

设计模式23种,https://www.cnblogs.com/wangzhongqiu/p/6245820.html

25.线程间通讯数据

http://www.importnew.com/26850.html

26.Android进程间通信

Activity

Activity的跨进程访问与进程内访问略有不同。虽然它们都需要Intent对象,但跨进程访问并不需要指定Context对象和Activity的 Class对象,而需要指定的是要访问的Activity所对应的Action(一个字符串)。有些Activity还需要指定一个Uri(通过 Intent构造方法的第2个参数指定)。

 在android系统中有很多应用程序提供了可以跨进程访问的Activity,例如,下面的代码可以直接调用拨打电话的Activity。
 Intent callIntent = new  Intent(Intent.ACTION_CALL, Uri.parse("tel:12345678" );  
 startActivity(callIntent);

Content Provider

Android应用程序可以使用文件或SqlLite数据库来存储数据。Content Provider提供了一种在多个应用程序之间数据共享的方式(跨进程共享数据)

BroadcastReceiver

通过发送广播给其他进程。

aidl

27.排序方式有哪几种

https://www.cnblogs.com/onepixel/articles/7674659.html

1.冒泡排序
冒泡排序是一种简单的排序算法,一次比较两个元素,如果它们的顺序错误就把它们交换过来。
选择排序
选择排序(Selection-sort)是一种简单直观的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,放在排序序列末尾

28.查找方式有哪几种

https://www.cnblogs.com/yw09041432/p/5908444.html
顺序查找,顺序查找的时间复杂度为O(n)。
二分查找,元素必须是有序的,如果是无序的则要先进行排序操作。最坏情况下,关键词比较次数为log2(n+1),且期望时间复杂度为O(log2n);
插值查找,基本思想:基于二分查找算法,将查找点的选择改进为自适应选择,可以提高查找效率。当然,差值查找也属于有序查找。
斐波那契查找
树表查找,基本思想:二叉查找树是先对待查找的数据进行生成树,确保树的左分支的值小于右分支的值,然后在就行和每个节点的父节点比较大小,查找最适合的范围。 这个算法的查找效率很高,但是如果使用这种查找方法要首先创建树。
哈希查找
分块查找,分块查找又称索引顺序查找,它是顺序查找的一种改进方法。
  算法思想:将n个数据元素"按块有序"划分为m块(m ≤ n)。每一块中的结点不必有序,但块与块之间必须"按块有序";即第1块中任一元素的关键字都必须小于第2块中任一元素的关键字;而第2块中任一元素又都必须小于第3块中的任一元素,……

29.图片加载框架有哪些,你用哪个,为什么用?

发展到现在Android的图片加载框架越来越成熟从一开始的UIL到后来的Glide、Picasso、fresco等。相比较而言Glide的功能更加强大,但是相应的方法数也是最多的。当然也得结合项目的需求还选择相应的框架。Glide比较吸引人的主要还是与Activity生命周期进行绑定、加载gif图片、可以配置相应的网络请求框架。

30.贝塞尔曲线

31.Android事件传递机制

在这里插入图片描述
在这里插入图片描述

32.Android View绘制流程

https://www.cnblogs.com/jycboy/p/6219915.html

33.android内存泄漏,如何防御

变量的声明周期超出了预期,就会发生内存泄漏
监听成对出现,变量生命周期能短就短,handler使用软引用。

34.屏幕适配

尺寸使用dp,或者使用根据屏幕等分的单位
使用不同的布局文件
布局尽量别大小
使用不同的密度图片

35.启动线程的方式(AsyncTask,thread,CountDownTimer,TimerTask)

36.surfaceView和view的区别

view在UI线程去更新自己;而SurfaceView则在一个子线程中去更新自己

37.完整的支付流程

38.性能分析工具

Android Studio中DDMS中

39.Activity,View,Window三者的关系

https://blog.csdn.net/freekiteyu/article/details/79408969

40.String的一些方法的理解

https://blog.csdn.net/manonghouyiming/article/details/79827040

41.Serializable 和Parcelable 的区别

Android中序列化有两种方式:Serializable以及Parcelable。其中Serializable是Java自带的,而Parcelable是安卓专有的。
两者区别在于存储媒介的不同。
Serializable使用IO读写存储在硬盘上。序列化过程使用了反射技术,并且期间产生临时对象。优点代码少。
Parcelable是直接在内存中读写,我们知道内存的读写速度肯定优于硬盘读写速度,所以Parcelable序列化方式性能上要优于Serializable方式很多。但是代码写起来相比Serializable方式麻烦一些。

42.string 转换成 integer的方式及原理

总结:integer.parseInt(string str)方法调用Integer内部的
parseInt(string str,10)方法,默认基数为10,parseInt内部首先
判断字符串是否包含符号(-或者+),则对相应的negative和limit进行
赋值,然后再循环字符串,对单个char进行数值计算Character.digit(char ch, int radix)
在这个方法中,函数肯定进入到0-9字符的判断(相对于string转换到int),
否则会抛出异常,数字就是如上面进行拼接然后生成的int类型数值。

43.List,Set,Map的区别

https://www.cnblogs.com/yangliguo/p/7476788.html

44.线程池

CachedThreadPool:可缓存的线程池,该线程池中没有核心线程,非核心线程的数量为Integer.max_value,就是无限大,当有需要时创建线程来执行任务,没有需要时回收线程,适用于耗时少,任务量大的情况。

SecudleThreadPool:周期性执行任务的线程池,按照某种特定的计划执行线程中的任务,有核心线程,但也有非核心线程,非核心线程的大小也为无限大。适用于执行周期性的任务。

SingleThreadPool:只有一条线程来执行任务,适用于有顺序的任务的应用场景。

FixedThreadPool:定长的线程池,有核心线程,核心线程的即为最大的线程数量,没有非核心线程

45.如何加载一张大图

com.github.chrisbanes.photoview.PhotoView

46.RecyclerView和ListView的性能对比

1 Listview中ViewHolder是需要自定义的,在RecyclerView中ViewHolder是谷歌已经封装好的

2 Listview中的Item是只能垂直滑动的,RecyclerView可以水平滑动或者垂直滑动,针对多种类型条目的展示效果,如瀑布流 网格 支持多种类型

3 Listview中删除或添加item时,item是无法产生动画效果的,在RecyclerView中添加、删除或移动item时有两种默认的效果可以选择SimpleItemAnimator(简单条目动画) 和 DefaultItemAnimator(原样的条目动画)。

47.NDK

猜你喜欢

转载自blog.csdn.net/w517272812/article/details/88707538