android面试题及答案汇总

1.如何对Android应用进行性能分析
TraceView:开始前调用 Android SDK中Debug类的startMethodTracing函数,并在关键代码段结束前调用 stopMethodTracing函数
Android性能主要之响应速度和UI刷新速度
首先从函数的耗时来说,有一个工具TraceView这是AndroidSDK自带的工具,用于测量函数耗时的。
UI布局的分析,可以有2块,一块就是HierarchyViewer可以看到view的布局层次,以及每个view刷新加载的时间。
2.什么情况下会导致内存泄漏
(1)静态集合类引起内存泄漏。主要是hashMap,Vector等。如果是静态集合这些集合没有及时set null的话。短周期对象就无法及时释放
(2)observer我们在使用监听器的时候,往往是addxxxlistener,但是当我们不需要的时候,忘记removexxxlistener,就容易内存leak。
(3)广播没有unregisterRecevier
(4)数据连接没有关闭,数据库contentProvider,IO,等
(5)内部类:Java中的内部类,会持有宿主的强引用this。如果是new Thread这种,后台线程的操作,当线程没有执行结束时,activity不会被回收。
(6)单例是一个全局的静态对象,当持有某个的类A,A无法释放
3.如何避免OOM异常(当应用程序需要申请一段大内存,但是虚拟机没有办法及时的给到)
减少内存对象的占用:减少bitmap的内存占用,减少资源图片的大小,避免在Android里面使用Enum,优化布局层次,减少内存消耗
内存对象的重复利用:listView/GridView/RecycleView中对contentView的复用,避免在onDraw方法里面new对象,stringBuilder代替+,复用系统自带的资源,Bitmap对象的复用
内存溢出通俗理解就是软件(应用)运行需要的内存,超出了它可用的最大内存。
内存泄漏就是我们对某一内存空间的使用,使用完成后没有释放。
4.ANR是什么?怎么避免和解决ANR
在规定的时间内,没有响应按键或触摸事件在特定时间内无响应
broadcastReceiver在特定时间内无法处理完成
ANR的关键是处理超时所以应该避免在UI线程,BroadCastReceiver还是service主线程中,处理复杂的逻辑和计算。
5.Android线程间通信有哪几种方式
共享变量,handle机制,thread,广播
6.dalvik进程,Linux进程,线程的区别
每个Android APP都会独立占用一个dvm虚拟机,运行在Linux系统中。所以dalvik进程和Linux进程是可以理解为一个概念
7.解释下Android程序运行时权限和文件系统权限的区别
文件的系统权限是由Linux系统规定的,只读,读写等
运行时权限,是对于某个系统上的APP来访问权限,允许,拒绝,询问,该功能可以防止非法的程序访问敏感信息。
8.FrameWork工作方式及原理,activity是如何生成一个view的,机制是什么
Framework是Android系统对Linux,lib库等封装,提供WMS,AMS,bind机制,handler-message机制等方式,供APP使用简单来说framework就是提供APP生存的环境。Activity在attach方法的时候,会创建一个phoneWindow。onCreate中的setContentView方法来创建一个window,会通过getDecorView生成view对象,通过addView方法,会把layout中的布局加载进来
9.Android中的动画有哪几种,他们的特点和区别是什么
视图动画或者说补间动画。只是视觉上的一个效果,实际view属性没有变化,性能好,支持方式少
属性动画,通过改变属性来达到动画的效果,性能略差,支持点击等事件。Android3.0加入
帧动画,通过drawable一帧帧画出来。
10.如何修改activity进入和退出动画
overridePendingTransition
11.SurfaceView和view的区别
view的更新必须在UI thread中进行SurfaceView会单独有一个线程做UI的更新SurfaceView支持open GL绘制surfaceChanged大小发生变化,surfaceCreated创建的时候激发,SurfaceDestroyed()销毁时激发
11.数组和集合类的区别
数组长度固定,集合长度可变。数组中只能存储同种基本类型的对象,集合可以存储多种类型的对象。
12.面向对象的特征有哪些方面?
抽象性:抽象就是忽略一个主题中与当前目标无关的哪些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而是选择其中一部分,暂时不用部分细节。过程抽象和数据抽象
继承:继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法
封装:封装就是把过程和数据包围起来,对数据的访问只能通过已定义的界面。
多态性:多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性
13.访问修饰符public private protected 以及不写时的区别?
public 公共的修饰符
private 当前类的修饰符
protected 当前类,子类,同包修饰符
default 当前类和同包修饰符
14.&与&&的区别?
&按位与:对每一个都判断
&&只要前面是false就输出false,而不继续判断后面了
15.Math函数方法
Math.round()四舍五入
Math.ceil()得到不小于某数的最小整数
Math.floor()得到不大于某数的最大整数
16.最有效的方法计算2乘以8?
2 << 3;
17.构造器(constructor)是否可被重写(override)?
能够被重载,不能被重写。
18.是否可以继承String类?
String类是final类故不可以继承。一切由final修饰过的都不能继承。
19.string与stringBuilder和stringBuffer区别?
String字符串常量:String是不可变的对象,因此在每次对String类型进行改变的时候其实都等于生成了一个新的String对象
StringBuffer字符串变量(线程安全):每次改变结果都会对StringBuffer对象本身进行操作,而不是生成新的对象
StringBuilder字符串变量(非线程安全)
20.重载(overload)和重写(override)的区别。
重载:方法重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型。重载是一个类中多态性的一种表现。就是在类中可以创建多个方法,他们具有相同的名字,但具有不同的参数和不同的定义。调用方法时通过传递给它们不同参数个数和参数类型来决定具体使用哪个方法。方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可以不相同。
重写:父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写。
21.静态与非静态的区别(静态类不能实例化,静态类中不能创建非静态的方法)
静态方法属于类所有,类实例化前即可使用。非静态方法可以访问类中的任何成员,静态方法只能访问类中的静态成员
因为静态方法在类实例化前就使用,而类中的非静态变量必须在实例化之后才能分配内存static内部只能出现static变量和其他static方法,而且static方法中不能使用this等关键字,因为它是属于整个类静态方法效率要比实例化高,静态方法不自动进行销毁,而实例化的则可以做销毁
22.GC是什么?为什么要有GC?
垃圾回收机制
23.Java中的final关键字有哪些用法?
使用final修饰的类不能被继承,final修饰的方法不可重写,final修饰的变量只能赋值一次。
24.try{}里面一个return语句,那么finally{}里的代码会不会被执行,什么时候被执行?在return前还是后?
会执行,在执行return后执行
25.描述final,finally,finalize的区别?
final:Java中的关键字,修饰符
如果一个类被声明为final,就意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能同时被声明为absrtac抽象类和final的类,如果将变量或者方法声明为final,可以保证它们在使用中不被改变
finally:Java的一种异常处理机制
finally是对Java异常处理模型的最佳补充。finally结构使代码总会被执行,而不管有无异常发生。使用finally可以维护对象的内部类状态,并可以清理非内存资源。
finalize:Java中的一个方法名
Java技术使用finalize()方法在垃圾收集器将对象从内存中清除出去前,做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。
26.Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别?
sleep()方法是线程类的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会让给其他线程,但是对象的锁依然保持,因此在休眠结束后会自动回复
wait()是object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池,只有调用对象的notify()方法时太能唤醒等待池中的线程进入等锁池,如果线程重新获得对象的锁就可以进入就绪状态。
27.堆和栈的区别
堆是先进先出
栈是先进后出
28.listView错乱原因:
1.listView item的缓存机制:
为了使用性能更优,listView会缓存行item。listView通过adapter的getView函数获得每行item,如果某行item已经滑出屏幕,若该item不在缓存内,则put进缓存,否则更新缓存;获取滑入屏幕的行item之前会先判断缓存中是否有可用的item,如果有做为convertView参数传递给adapter的getView
2.行item图片显示重复
异步加载图片滑动快加载慢,造成显示重复
3.行item图片显示错乱
比如ListView滑动到第2行会异步加载某个图片,但是加载很慢,加载过程中listView已经滑动到了第14行,第2行已不在屏幕内,根据上面介绍的缓存原理,第2行的view可能被第14行复用,第14行显示了第2行的View,这时之前的图片加载结束,就会显示在第14行,造成错乱
4.行item图片显示闪烁
有很快加载结束,先显示缓存的图片,立马又显示了自己的图片进行覆盖造成闪烁错乱
解决方案
通过上面的分析我们知道了出现错乱的原因是异步加载及对象被复用造成的,如果每次getView能给对象一个标识,在异步加载完成时比较标识与当前行item的标识是否一致,一致则显示,否则不做处理即可listView中加载不同的item使用geiItemViewType和使用getViewTypeCount设置item样式数
29.activity的启动模式
1.standard:标准
2.singleTop:单一的
3.singleTask:单任务
4.singleInstance:单例
设置Android的启动模式在AndroidManifest.xml里面对应的标签设置launchMode属性
1.standard:默认模式,可以不用写配置。因此在这个模式下可以有多个相同的实例,也可以有多个相同的activity叠加。点击back键会依照栈的顺序依次退出
2.singleTop:允许有多个实例但是不允许有多个activity叠加。即如果activity在栈顶的时候,启动相同的activity不会创建新的实例,而会调用其onNewIntent方法
3.只会有一个实例,在同一个应用程序中启动它的时候,若activity不存在,则在当前的task创建一个新的实例。若存在则会把task中之上的其他activity destroy掉并调用它的onNewIntent方法
如果在其他应用中启动它,则会新建一个task,并在这个task中启动这个activity。singleTask允许别的activity在一个task中存在
4.只有一个实例,并且这个实例独立运行在一个task中,这个task只有这个实例,不允许有别的activity存在
30.dvm进程与Linux进程,应用程序的进程是否为同一概念。
Dvm进程是dalvik虚拟机进程,,每个Android程序都运行在自己进程里,每个Android程序系统都会给他分配一个独立的Linux uid(user id),每个dvm都是linux里面的一个进程.所以说这两个进程是一个进程.
31.dalvik和Java运行环境的区别
1.dalvik主要完成对象生命周期管理,堆栈管理,线程管理,安全和异常管理,以及垃圾回收等重要功能
2.Dalvik负责进程隔离和线程管理,每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行。
3.不同于Java虚拟机运行Java字节码,Dalvik虚拟机运行的是其专有的文件格式Dex
4.dex文件格式可以减少整体文件尺寸,提高I/O操作的类查找速度
5.odex是为了在运行过程中进一步提高性能,对dex文件的进一步优化。
6.所有的Android应用的线程都对应一个Linux线程,虚拟机因而可以更多的依赖操作系统和线程调度和管理
32.进程与线程之间的区别
进程:进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是一个系统进行资源分配和调度的一个独立单位
线程:线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位,线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源,但是他可与同属一个进程的其他的线程共享进程所拥有的资源
一个线程可以创建和撤销另一个线程;同一个进程中的多线程之间可以并发执行
区别:进程和线程的主要区别在于它们是不同操作系统资源管理方式。进程独立运行在地址空间,一个进程崩溃后,在保护模式下不会对其他进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独地址空间,一个线程死掉就等于整个进程死掉。
33.Dalvik和ART的区别
ART能够把应用程序的字节码转为机器码,是Android所使用的一种新的虚拟机,与Dalvik不同在于:Dalvik采用的是JIT技术而ART采用Ahead-of-time(AOT)技术。ART同时也改善了性能,垃圾回收机制,应用程序出错以及性能分析
ART引入了AOT这种预编译技术,在应用程序安装的过程中,ART就已经将所有的字节码重新编译成机器码。应用程序运行过程中无需进行实时的编译工作,只需要进行直接调用,因此ART极大的提高了应用程序的运行效率,同时也减少了手机的电量消耗,在垃圾回收机制等机制上也有了较大的提升。
相对于Dalvik虚拟机模式。ART模式下Android应用程序的安装需要消耗更多的时间,同时也会占用更大的存储空间(指内部存储,用于存储编译后的代码),但节省了很多dalvik虚拟机用于实时编译的时间
34.Java四类八种数据类型
基本数据类型:byte 1 short 2 int 4 long 8 float 4 double 8 char boolean
应用数据类型:class interface 数组
char类型站2个字节
short从-32768到32767
int从-2147483648到2147483647共10王
long从-9223372036854775808到9223372036854775807共19位
35.view中getRowX和getX的区别
getRowX:触摸点相对于屏幕的坐标
getX:触摸点相对于按钮的坐标
36.Android的五大布局
LinearLayout:线性布局按照垂直或者水平的顺序依次排列子元素
FrameLayout:单帧布局所以的子元素都不能被指定放置位置,全部放于这块区域的左上角,后面的子元素直接覆盖在前面的子元素之上
RelativeLayout:相对布局按照各个子元素之间的位置关系完成布局
AbsolutLayout:绝对布局子元素的layout_x和layout_y属性将生效,用于描述该子元素的坐标位置
TableLayout:表格布局一个TableLayout由许多TableRow组成,一个TableRow就代表一行
37.Android四大组件
Activity,Service,BroadcastReceiver,ContentProvider
38.listView性能优化
1.在adapter中的getView方法中尽量少使用逻辑
2.尽最大可能避免GC
3.滑动的时候不加载图片
4.使用viewHolder
5.将ListView的scrollingCache和animateCache设置为false
6.item的布局层级越少越好
7.Adapter的getView方法里面convertView使用setTag和getTag方式
39.设计一个图片缓存加载机制
先检查在内存中是否存在该图片,在检查在硬盘中是否存在该图片,最后在网络上获取图片
40.视频播放插件
mediaPlayer
surfaceView
41.图片加载框架
ImageLoader
glide
volley
XUtils
42.监听listView和gridView页面滑动到底部
重写onScrollStateChanged方法获取可见item的数量
重写onScroll方法获取可见item的数量和项目列表中适配器的数量
ExpandableListView
43.Android与js交互
交互的接口函数:mWebView.addJavascriptInerface(getHtmlObject(),“”)
代码端是通过loadUrl函数实现的(函数需在UI线程运行,因为mWebView为UI控件)
Android允许实现脚本设置:webSettings.addJavascriptEnabled(true)
Android访问url网址需要在AndroidManifest.xml文件
44.更新单条的listView属性
使用getFirstVisiblePosition()
getLastVisiblePosition()
getItemAtPosition(int position):该方法返回当前状态下position位置上listView的convertView

public void updateSingleRow(ListView listView, long id) {
        if (listView != null) {
            int start = listView.getFirstVisiblePosition();
            for (int i = start, j = listView.getLastVisiblePosition(); i <= j; i++) {
                if (id == i) {
                    View view = listView.getChildAt(i - start);
                    a = 4;
                    getView(i, view, listView);
                    break;
                }
            }
        }
    }

你可能感兴趣的:(android面试题及答案汇总)