Android 面试题总结
1.Android四大组件以及作用???
Activity(活动):Activity是Android程序与用户实现交互的窗口,是Android中最重要的一中,它需要保存各界面的状态,做很多持久化的事情。
Service(服务):运行与后台服务于Activity,定义好接受的Intent提供同步和异步的接口。 service 有两种启动方式: startService()与bindService()
service两种启动方式区别:startService只是启动Service,启动它的组件(如Activity)和Service并没有关联,只有当Service调用stopSelf或者其他组件调用stopService服务才会终止。
bindService方法启动Service,其他组件可以通过回调获取Service的代理对象和Service交互,而这两方也进行了绑定,当启动方销毁时,Service也会自动进行unBind操作,当发现所有绑定都进行了unBind时才会销毁Service。
Service的onCreate回调函数可以做耗时的操作吗?
不可以,Service的onCreate是在主线程(ActivityThread)中调用的,耗时操作会阻塞UI
Content Provider(内容提供者): android平台提供了Content Provider使一个应用程序的指定数据集提供给其他应用程序。其他应用可以通过ContentResolver类从该内容提供者中获取或存入数据。
BroadCast Receiver(广播接收着):广播是一种广泛运用的在应用程序之间传输信息的机制。而广播接收器是对发送出来的广播进行过滤接受并响应的一类组件。可以使用广播接收器来让应用对一个外部时间做出响应。
广播接收者的注册有两种方法,分别是程序动态注册(在运行时的代码中使用Context.registerReceive()进行注册)和AndroidManifest文件中进行静态注册。
动态注册广播接收器特点是当用来注册的Activity关掉后,广播也就失效了。静态注册无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器也是打开着的。也就是说哪怕app本身未启动,该app订阅的广播在触发时也会对它起作用。
2.Android中常用的五中布局???
FrameLayout(帧布局):显示特点:所有的子控件默认显示在FrameLayout的左上角,会重叠在一起显示。
LinearLayout(线性布局):显示特点:所有子控件按照横向或者竖向依次排列,android:orientation="vertical"(竖向),android:orientation="horizontal"(横向)。
RelativeLayout(相对布局):显示特点:和LinearLayout布局相似,所有子控件默认显示在RelativeLayout的左上角 GridLayout(网格布局):显示特点:所有子控件默认在GridLayout中横向依次排列,当只等每行的列数时,到达指定列数 TableLayout(表格布局):表格布局和网格布局类似,但是需要注意的是,表格布局不能跨行,只能跨列
3.Android 中动画有哪几类???它们的特点和区别是什么???
两类,一类是Tween动画、另一类是Frame动画。
Tween动画,实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化。
Frame动画,通过一定的顺序来播放一组图片,(如gif图)。
4.Android中Listview优化方案???
如果是自定义适配器,那么在getView方法中考虑传进来额参数contenView是否为null,如果不为null则直接使用,尽量减少view的创建。
给contentView设置tag(setTag()),传入viewHolaer对象,用于缓存要显示的数据,可以达到图像数据的异步加载。
如果Listview需要显示的item比较多时,就要考虑数据的分页加载,根据需求去对应加载数据。
5.ArrayList与LinkedList的区别和适用场景???
Arraylist:
优点:ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的)。
缺点:因为地址连续, ArrayList要移动数据,所以插入和删除操作效率比较低。
LinkedList:
优点:LinkedList基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,对于新增和删除操作add和remove,LinedList比较占优势。LinkedList 适用于要头尾操作或插入指定位置的场景。
缺点:因为LinkedList要移动指针,所以查询操作性能比较低。
适用场景分析: 当需要对数据进行对此访问的情况下选用ArrayList,当需要对数据进行多次增加删除修改时采用LinkedList。
6.View的绘制流程???
View的绘制流程:Measure()——>OnLayout()——>OnDraw()
各步骤的主要工作:
Measure():
测量视图大小。从顶层父View到子View递归调用measure方法,measure方法又回调OnMeasure。
OnLayout():
确定View位置,进行页面布局。从顶层父View向子View的递归调用view.layout方法的过程,即父View根据上一步measure子View所得到的布局大小和布局参数,将子View放在合适的位置上。
OnDraw():
绘制视图:ViewRoot创建一个Canvas对象,然后调用OnDraw()。六个步骤:①、绘制视图的背景;②、保存画布的图层(Layer);③、绘制View的内容;④、绘制View子视图,如果没有就不用;⑤、还原图层(Layer);⑥、绘制滚动条。
7.activity的生命周期???
Activity生命周期方法主要有onCreate()、onStart()、onResume()、onPause()、onStop()、onDestroy()和onRestart()方法。 启动一个A Activity,分别执行onCreate()、onStart()、onResume()方法。 从A Activity打开B Activity分别执行A onPause()、B onCreate()、B onStart()、B onResume()、A onStop()方法。 关闭B Activity,分别执行B onPause()、A onRestart()、A onStart()、A onResume()、B onStop()、B onDestroy()方法。 横竖屏切换A Activity,清单文件中不设置android:configChanges属性时,先销毁onPause()、onStop()、onDestroy()再重新创建onCreate()、onStart()、onResume()方法,设置orientation|screenSize(一定要同时出现)属性值时,不走生命周期方法,只会执行onConfigurationChanged()方法。 Activity之间的切换可以看出onPause()、onStop()这两个方法比较特殊,切换的时候onPause()方法不要加入太多耗时操作否则会影响体验。
8.android的数据存储???
使用SharedPreferences存储数据;它是Android提供的用来存储一些简单配置信息的一种机制,采用了XML格式将数据存储到设备中。只能在同一个包内使用,不能在不同的包之间使用。 文件存储数据;文件存储方式是一种较常用的方法,在Android中读取/写入文件的方法,与Java中实现I/O的程序是完全一样的,提供了openFileInput()和openFileOutput()方法来读取设备上的文件。 SQLite数据库存储数据;SQLite是Android所带的一个标准的数据库,它支持SQL语句,它是一个轻量级的嵌入式数据库。 使用ContentProvider存储数据;主要用于应用程序之间进行数据交换,从而能够让其他的应用保存或读取此Content Provider的各种数据类型。 网络存储数据;通过网络上提供给我们的存储空间来上传(存储)和下载(获取)我们存储在网络空间中的数据信息。
9.Activity启动模式???
standard:标准模式,也是系统默认的启动模式。假如 activity A 启动了 activity B , activity B 则会运行在 activity A 所在的任务栈中。而且每次启动一个 Activity ,都会重新创建新的实例,不管这个实例在任务中是否已经存在。
singleTop:栈顶复用模式。假如 activity A 启动了 activity B ,就会判断 A 所在的任务栈栈顶是否是 B 的实例。如果是,则不创建新的 activity B 实例而是直接引用这个栈顶实例,同时 onNewIntent 方法会被回调,通过该方法的参数可以取得当前请求的信息;如果不是,则创建新的 activity B 实例。
singleTask:栈内复用模式。在第一次启动这个 Activity 时,系统便会创建一个新的任务,并且初始化 Activity 的实例,放在新任务的底部。不过需要满足一定条件的。那就是需要设置 taskAffinity 属性。
singleInstance:单实例模式。这个是 singleTask 模式的加强版,它除了具有 singleTask 模式的所有特性外,它还有一点独特的特性,那就是此模式的 Activity 只能单独地位于一个任务栈,不与其他 Activity 共存于同一个任务栈。
10.广播注册???
首先写一个类要继承BroadCastReceiver 第一种:在清单文件中声明,添加 第二种:使用代码进行注册如: <receive android :name ="BroadCastReceiverDemo"> <intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED"> </intent-filter> </receiver> 第二种:使用代码进行注册如: IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); BroadCastReceiverDemo receiver = new BroadCastReceiver(); registerReceiver(receiver, filter); 两种注册类型的区别是: 第一种是常驻型广播,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。 第二种不是常驻广播,也就是说广播跟随程序的生命周期。
11.ListView和RecycleView的比较区别
1.布局效果上 :recycleview支持三种布局(RecyclerView 就能支持 线性布局、网格布局、瀑布流布局 三种(这里我们暂且不提代码细节,后文再说),而且同时还能够控制横向还是纵向滚动)
2.对于条目的复用上,不像listview总是重复的调用setTag
3.动画条目:recycleview比起listview,在更新条目的时候,有渐变,对于增删移动。根据继承RecycleView.ItemAnimator,然后setItemAnimator。 如果想要自定义条目动画,那就是ItemTouchHelpter,里面的三个抽象方法: getMovementFlags 、 onMove 、 onSwiped
4.局部刷新:listview有刷新,但是局部没有,每次都要对每一个Item重新绘制,但是对于一些点赞逻辑,并不需要,所以我们可以根据API给我们的updateItemView==换算成itemview在viewgroup中的index,判断更新条目的下标,然后刷新
5.添加头布局和脚布局:对于监听,listview的下标会混乱。
6.空数据处理:listview有一个setEmptyView来处理数据为空,但是Recycleview没有,需要自己来写。
7.镶套机制:listview不支持。重点在于NestedScrollingChild和NestedScrollingParent两个接口。为了是子布局和父布局同时被滑动。
8.listview:继承重写baseadpter,自定义viewholder和convertview,完成复用和优化
9.Recycleview使用继承和重写RecycleviewAdapter和RecycleView.ViewHolder(布局管理器 API文档很多效果,对于瀑布流我们需要在xml里面设置,如果还去adapter里面去设置,那就失去了layoutmanager的设计理念啦。)
10.ListView 提供了 setEmptyView 这个 API 来让我们处理 Adapter 中数据为空的情况,只需轻轻一 set 就能搞定一切。代码设置和效果如下
mListView = (ListView) findViewById(R.id.listview);
mListView.setEmptyView(findViewById(R.id.empty_layout));//设置内容为空时显示的视图
11.而 RecyclerView 并没有提供此类 API,所以,这些工作需要自己来干。
12.通过流程图来分析Android事件分发
1.触摸事件,大多就是按下(down)、移动(move)、抬起(up),有时候你可能会遇到取消(cancel)事件
2.从dispatchTouchEvent()开始,进入当前View的事件分发流程,该方法只负责分发事件,没有实际进行事件处理。
3.有可能处理事件的有两个地方,一个是外部设置的OnTouchListener监听器,即OnTouchListener的onTouch(),一个是View内部的处理方法,即onTouchEvent()。而且外部设置的监听器优先获取事件。
4.当外部设置的监听器处理了事件(即有设置监听器、View处于ENABLE状态、监听器在onTouch()里面返回true三者均成立),dispatchTouchEvent()返回true,当前View的onTouchEvent()不会触发。
5.如果外部的监听器不处理事件,则dispatchTouchEvent()的返回值由View自己的onTouchEvent()决定。
13.String能被继承吗?为什么?
不可以,因为String类有final修饰符,而final修饰的类是不能被继承的,实现细节不允许改变。平常我们定义的String str=”a”;其实和String str=new String(“a”)还是有差异的。
14.String, Stringbuffer, StringBuilder 的区别。
1.String 字符串常量(final修饰,不可被继承),String是常量,当创建之后即不能更改。(可以通过StringBuffer和StringBuilder创建String对象(常用的两个字符串操作类)。) 2.==StringBuffer 字符串变量(线程安全),==其也是final类别的,不允许被继承,其中的绝大多数方法都进行了同步处理,包括常用的Append方法也做了同步处理(synchronized修饰)。其自jdk1.0起就已经出现。其toString方法会进行对象缓存,以减少元素复制开销 3.==StringBuilder 字符串变量(非线程安全)==其自jdk1.5起开始出现。与StringBuffer一样都继承和实现了同样的接口和类,方法除了没使用synch修饰以外基本一致,不同之处在于最后toString的时候,会直接返回一个新对象。
15ArrayList 和 LinkedList 有什么区别。
ArrayList和LinkedList都实现了List接口,有以下的不同点: 1、ArrayList是基于索引的数据接口,它的底层是数组。它可以以O(1)时间复杂度对元素进行随机访问。与此对应,LinkedList是以元素列表的形式存储它的数据,每一个元素都和它的前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n)。 2、相对于ArrayList,LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。 3、LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。
16.用过哪些 Map 类,都有什么区别,HashMap 是线程安全的吗,并发下使用的 Map 是什么,他们内部原理分别是什么,比如存储方式, hashcode,扩容, 默认容量等。
hashMap是线程不安全的,HashMap是数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的,采用哈希表来存储的
17.抽象类和接口的区别,类可以继承多个类么,接口可以继承多个接口么,类可以实现多个接口么。
1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。 2、抽象类要被子类继承,接口要被类实现。 3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现 4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。 5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。 6、抽象方法只能申明,不能实现。abstract void abc();不能写成abstract void abc(){}。 7、抽象类里可以没有抽象方法 8、如果一个类里有抽象方法,那么这个类只能是抽象类 9、抽象方法要被实现,所以不能是静态的,也不能是私有的。 10、接口可继承接口,并可多继承接口,但类只能单根继承。
18.final 的用途
final 修饰的类叫最终类,该类不能被继承。 final 修饰的方法不能被重写。 final 修饰的变量叫常量,常量必须初始化,初始化之后值就不能被修改。
19.JDK 和 JRE 有什么区别?
JDK:Java Development Kit 的简称,java 开发工具包,提供了 java 的开发环境和运行环境。
JRE:Java Runtime Environment 的简称,java 运行环境,为 java 的运行提供了所需环境。
具体来说 JDK 其实包含了 JRE,同时还包含了编译 java 源码的编译器 javac,还包含了很多 java 程序调试和分析的工具。简单来说:如果你需要运行 java 程序,只需安装 JRE 就可以了,如果你需要编写 java 程序,需要安装 JDK。
20.== 和 equals 的区别是什么?
对于基本类型和引用类型 == 的作用效果是不同的,如下所示:
基本类型:比较的是值是否相同;
引用类型:比较的是引用是否相同;
21.String 类的常用方法都有那些?
indexOf():返回指定字符的索引。 charAt():返回指定索引处的字符。 replace():字符串替换。 trim():去除字符串两端空白。 split():分割字符串,返回一个分割后的字符串数组。 getBytes():返回字符串的 byte 类型数组。 length():返回字符串长度。 toLowerCase():将字符串转成小写字母。 toUpperCase():将字符串转成大写字符。 substring():截取字符串。 equals():字符串比较。
22.Android 中如何实现多线程编程
努力不是表现给谁看的,而是从小白渐渐走向牛X的过程!!!