Android面试题总结分析

1.View、SurfaceView、GLSurfaceView的关系和区别?
答:View:显示视图,内置画布,提供图形绘制函数、触屏事件、按键事件函数等;必须在UI主线程内更新画面,速度较慢
SurfaceView:基于view视图进行拓展的视图类,更适合2D游戏的开发;是view的子类,类似使用双缓机制,在新的线程中更
新画面所以刷新界面速度比view快。
GLSurfaceView:基于SurfaceView视图再次进行拓展的视图类,专用于3D游戏开发的视图;是SurfaceView的子类,openGL专用。

View和SurfaceView区别:
    View:必须在UI的主线程中更新画面,用于被动更新画面。
     SurfaceView:UI线程和子线程中都可以。在一个新启动的线程中重新绘制画面,主动更新画面。
2.各种动画的区别,500张图片怎么使用帧动画实现,怎么避免OOM,平时用什么动画,属性动画和补间动画的区别是什么?
答:View Animation: 视图动画在古老的Android版本系统中就已经提供了,只能被用来设置View的动画。
Drawable Animation: 这种动画(也叫Frame动画、帧动画)其实可以划分到视图动画的类别,专门用来一个一个的显示
Drawable的resources,就像放幻灯片一样。
Property Animation: 属性动画只对Android 3.0(API 11)以上版本的Android系统才有效,这种动画可以设置给任何Object,
包括那些还没有渲染到屏幕上的对象。这种动画是可扩展的,
可以让你自定义任何类型和属性的动画

视图动画,也叫Tween(补间)动画可以在一个视图容器内执行一系列简单变换(位置、大小、旋转、透明度)。譬如,
如果你有一个TextView对象,您可以移动、旋转、缩放、透明度设置其文本,当然,如果它有一个背景图像,背景图像会随着文本变化。
Drawable动画其实就是Frame动画(帧动画),它允许你实现像播放幻灯片一样的效果,这种动画的实质其实是Drawable,
所以这种动画的XML定义方式文件一般放在res/drawable/目录下
Android 3.0以后引入了属性动画,属性动画可以轻而易举的实现许多View动画做不到的事,上面也看见了,
View动画无非也就做那几种事情,别的也搞不定,而 属性动画就可以的,譬如3D旋转一张图片。其实说白了,
你记住一点就行,属性动画实现原理就是修改控件的属性值实现的动画。
多张图片使用帧动画便面OOM:继承SurfaceView 

平时使用大多数是 View Animation(视图动画/补间动画) 也会用到属性动画;

当移动位置不是相对于ParentView或者Window时,补间动画只实现了View图像位置的改变,但控件并没有发生位移
当属性动画移动后,如果不会到原来的位置,那么点击新的位置,将接受不到Click事件,点击原来的位置可以接收到点击事件
补间动画通过不断的调用OnDraw方法来进行UI的绘制,而属性动画一般只调用ViewGroup进行绘制
属性动画不会主动恢复到原来的状态,而是一直保持新的状态,直到下一次改变
属性动画可以使用playToggther,play..with,play...[width]... after,playSequentaily进行动画的控制,使用起来非常方便
属性动画可以通过ObjectAnimator和PropertyValueHolder进行动态控制,增加了动画的灵活性
3.对懒加载的理解?
答:在应用程序中,系统的瓶颈常在于系统的响应速度。如果系统响应速度过慢,用户就会出现埋怨情绪,系统的价值也因此会大打折扣。
因此,提高系统响应速度,是非常重要的。
在Android应用程序中程序做的最多的就是显示数据,加载UI界面,有时候还会请求服务器获取数据。因为手机内存容量有限,
把过多的数据放在内存中,会影响电脑性能。而另一种技术,懒加载可以解决这种问题。
懒加载,通常是使用一定的方法使程序界面和请求接口数据在用户滑动页面或者触发某个特定事件时候触发加载数据或者刷新页面。
(个人理解,有比较好的理解请分享,谢谢!)
4.横竖屏切换生命周期的调用,怎么配置?
答:1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
2、设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
3、设置Activity的android:configChanges="orientation|screenSize"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法。
(执行这个方法,必须设置sdk version 大于等于13.0)

5.有几种广播,怎么配置,分别有什么区别,粘性广播是什么意思。系统之有那些用到了粘性广播?
答:BroadcastReceiver用于监听被广播的事件
必须被注册,有两种方法:
1、在应用程序的代码中注册
注册BroadcastReceiver:
registerReceiver(receiver,filter);
取消注册BroadcastReceiver:
unregisterReceiver(receiver);
当BroadcastReceiver更新UI,通常会使用这样的方法注册。启动Activity时候注册BroadcastReceiver,Activity不可见时候,取消注册。
2、在androidmanifest.xml当中注册
<receiver>
<intent-filter>
<action android:name = "android.intent.action.PICK"/>
</intent-filter>
</receiver>
1)第一种不是常驻型广播,也就是说广播跟随程序的生命周期。
2)第二种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。
使用androidmanifest注册的方法注册广播弊端:它会始终处于活动状态,毕竟是手机开发,cpu和电源资源比较少,一直处于活动耗费大
sendStickyBroadcast()字面意思是发送粘性的广播,使用这个api需要权限android.Manifest.permission.BROADCAST_STICKY,
粘性广播的特点是Intent会一直保留到广播事件结束,而这种广播也没有所谓的10秒限制,10秒限制是指普通的广播如果onReceive方法执行时间太长,
超过10秒的时候系统会将这个广播置为可以干掉的candidate,一旦系统资源不够的时候,就会干掉这个广播而让它不执行。
粘性消息:粘性消息在发送后就一直存在于系统的消息容器里面,等待对应的处理器去处理,如果暂时没有处理器处理这个消息则一直在消息容器里面处于等待状态,
粘性广播的Receiver如果被销毁,那么下次重建时会自动接收到消息数据。
在Android系统粘性广播一般用来确保重要的状态改变后的信息被持久保存,并且能随时广播给新的广播接收器,比如电源的改变,因为耗电需要一个过程,前一个过程必须提前得到,
否则可能遇到下次刚好接收到的广播后系统自动关机了,随之而来的是kill行为,所以对某些未处理完的任务来说,后果很严重
6.系统异常退出怎么保存数据,调用什么方法,怎么回复数据,在那里恢复?
答:临时数据使用 onSaveInstanceState 保存恢复,永久性数据使用 onPause 方法保存。因为Android的View本身自己就实现了onSaveInstanceState方法,这些控件自己就具有保存临时数据和恢复临时数据的能力。(不完善)
7.Fragment和FragmentPagerAdapter使用,Fragment在那个方法初始化?
答: FragmentPagerAdapter是Android-support-v4支持包里面出现的一个新的适配器,继承自PagerAdapter,是专门用来给支持包中出现的ViewPager进行数据适配的。
FragmentPagerAdapter,见名知意,这个适配器就是用来实现Fragment在ViewPager里面进行滑动切换的,因此,如果我们想实现Fragment的左右滑动,
可以选择ViewPager和FragmentPagerAdapter实现。
FragmentPagerAdapter拥有自己的缓存策略,当和ViewPager配合使用的时候,会缓存当前Fragment以及左边一个、右边一个,一共三个Fragment对象。
假如有三个Fragment,那么在ViewPager初始化之后,3个fragment都会加载完成,中间的Fragment在整个生命周期里面只会加载一次,当最左边的Fragment处于显示状态,
最右边的Fragment由于超出缓存范围,会被销毁,当再次滑到中间的Fragment的时候,最右边的Fragment会被再次初始化。


Fragment初始化的方法onCreateView返回Fragment 的View
8.什么情况下会导致内存泄漏,怎么避免,handler为什么会内存泄漏,怎么解决,为什么要用弱引用?
答:集合类如果仅仅有添加元素的方法,而没有相应的删除机制,导致内存被占用。如果这个集合类是全局性的变量 (比如类中的静态属性,
全局性的 map 等即有静态引用或 final 一直指向它),那么没有相应的删除机制,很可能导致集合所占用的内存只增不减。比如上面的典型例子就是其中一种情况,
当然实际上我们在项目中肯定不会写这么 2B 的代码,但稍不注意还是很容易出现这种情况,比如我们都喜欢通过 HashMap 做一些缓存之类的事,这种情况就要多留一些心眼。
单例造成的内存泄漏
由于单例的静态特性使得其生命周期跟应用的生命周期一样长,所以如果使用不恰当的话,很容易造成内存泄漏
匿名内部类/非静态内部类和异步线程
非静态内部类创建静态实例造成的内存泄漏
有的时候我们可能会在启动频繁的Activity中,为了避免重复创建相同的数据资源
Handler 造成的内存泄漏
andler 的使用造成的内存泄漏问题应该说是最为常见了,很多时候我们为了避免 ANR 而不在主线程进行耗时操作,在处理网络任务或者封装一些请求回调等api都借助Handler来处理,
但 Handler 不是万能的,对于 Handler 的使用代码编写一不规范即有可能造成内存泄漏。另外,我们知道 Handler、Message 和 MessageQueue 都是相互关联在一起的,
万一 Handler 发送的 Message 尚未被处理,则该 Message 及发送它的 Handler 对象将被线程 MessageQueue 一直持有。
由于 Handler 属于 TLS(Thread Local Storage) 变量, 生命周期和 Activity 是不一致的。因此这种实现方式一般很难保证跟 View 或者 Activity 的生命周期保持一致,
故很容易导致无法正确释放。
解决这个问题思路就是使用静态内部类并继承Handler时(或者也可以单独存放成一个类文件)。因为静态的内部类不会持有外部类的引用,所以不会导致外部类实例的内存泄露。
当你需要在静态内部类中调用外部的Activity时,我们可以使用弱引用来处理

弱引用与软引用的根本区别在于:只具有弱引用的对象拥有更短暂的生命周期,可能随时被回收。而只具有软引用的对象只有当内存不够的时候才被回收,在内存足够的时候,通常不被回收。

9.如何防止Service被Kill?
答:1. settings 中stop service
onDestroy方法中,调用startService进行Service的重启。
2.settings中force stop 应用
捕捉系统进行广播(action为android.intent.action.PACKAGE_RESTARTED)
3. 借助第三方应用kill掉running task
提升service的优先级,程序签名,或adb push到system\app下等
相较于/data/app下的应用,放在/system/app下的应用享受更多的特权,比如若在其Manifest.xml文件中设置persistent属性为true,则可使其免受out-of-memory killer的影响。如应用程序'Phone'的AndroidManifest.xml文件:
10.Binder机制?
答:Binder是Android系统进程间通信(IPC)方式之一
Linux已经拥有的进程间通信IPC手段包括(Internet Process Connection): 管道(Pipe)、信号(Signal)和跟踪(Trace)、插口(Socket)、报文队列(Message)、共享内存(Share Memory)和信号量(Semaphore)。
Binder基于Client-Server通信模式,传输过程只需一次拷贝,为发送发添加UID/PID身份,既支持实名Binder也支持匿名Binder,安全性高。
Binder可以看成Server提供的实现某个特定服务的访问接入点, Client通过这个‘地址’向Server发送请求来使用该服务;对Client而言,Binder可以看成是通向Server的管道入口,要想和某个Server通信首先必须建立这个
管道并获得管道入口。
Binder框架定义了四个角色:Server,Client,ServiceManager以及Binder驱动。其中Server,Client,ServiceManager运行于用户空间,
驱动运行于内核空间。这四个角色的关系和互联网类似:Server是服务器,Client是客户终端,ServiceManager是域名服务器(DNS),驱动是路由器。
11.什么是守护线程,该怎么理解?
答:在Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)   
Daemon的作用是为其他线程的运行提供便利服务,比如垃圾回收线程就是一个很称职的守护者。User和Daemon两者几乎没有区别,
唯一的不同之处就在于虚拟机的离开:如果 User Thread已经全部退出运行了,只剩下Daemon Thread存在了,虚拟机也就退出了。 因为没有了被守护者,Daemon也就没有工作可做了,也就没有继续运行程序的必要了。 
12.Android消息机制?
答:Android应用程序是通过消息来驱动的,系统为每一个应用程序维护一个消息队例,应用程序的主线程不断地从这个消息队例中获取消息(Looper),
然后对这些消息进行处理(Handler),这样就实现了通过消息来驱动应用程序的执行
在消息处理机制中,消息都是存放在一个消息队列中去,而应用程序的主线程就是围绕这个消息队列进入一个无限循环的,直到应用程序退出。
如果队列中有消息,应用程序的主线程就会把它取出来,并分发给相应的Handler进行处理;如果队列中没有消息,应用程序的主线程就会进入空闲等待状态,等待下一个消息的到来。
 A. Android应用程序的消息处理机制由消息循环、消息发送和消息处理三个部分组成的。
         B. Android应用程序的主线程在进入消息循环过程前,会在内部创建一个Linux管道(Pipe),这个管道的作用是使得Android应用程序主线程在
         消息队列为空时可以进入空闲等待状态,并且使得当应用程序的消息队列有消息需要处理时唤醒应用程序的主线程。
         C. Android应用程序的主线程进入空闲等待状态的方式实际上就是在管道的读端等待管道中有新的内容可读,具体来说就是是通过Linux系统的Epoll机制中的epoll_wait函数进行的。
         D. 当往Android应用程序的消息队列中加入新的消息时,会同时往管道中的写端写入内容,通过这种方式就可以唤醒正在等待消息到来的应用程序主线程。
         E. 当应用程序主线程在进入空闲等待前,会认为当前线程处理空闲状态,于是就会调用那些已经注册了的IdleHandler接口,使得应用程序有机会在空闲的时候处理一些事情。
 
13.滑动冲突解决,事件分发机制?
答:android系统中的每个View的子类都具有下面三个和TouchEvent处理密切相关的方法:
1)public boolean dispatchTouchEvent(MotionEvent ev)  这个方法用来分发TouchEvent
2)public boolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent
3)public boolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent


当TouchEvent发生时,首先Activity将TouchEvent传递给最顶层的View, TouchEvent最先到达最顶层 view 的 dispatchTouchEvent ,
然后由  dispatchTouchEvent 方法进行分发,如果dispatchTouchEvent返回true ,则交给这个view的onTouchEvent处理,如果dispatchTouchEvent返回 false ,则交给这个 view 的 interceptTouchEvent 方法来决定是否要拦截这个事件,
如果 interceptTouchEvent 返回 true ,也就是拦截掉了,则交给它的 onTouchEvent 来处理,如果 interceptTouchEvent 返回 false ,那么就传递给子 view ,由子 view 的 dispatchTouchEvent 再来开始这个事件的分发。如果事件传递到某一层的子 view 的 onTouchEvent 上了,
这个方法返回了 false ,那么这个事件会从这个 view 往上传递,都是 onTouchEvent 来接收。而如果传递到最上面的 onTouchEvent 也返回 false 的话,这个事件就会“消失”,而且接收不到下一次事件。
1. Android事件分发是先传递到ViewGroup,再由ViewGroup传递到View的。
2. 在ViewGroup中可以通过onInterceptTouchEvent方法对事件传递进行拦截,onInterceptTouchEvent方法返回true代表不允许事件继续向子View传递,返回false代表不对事件进行拦截,默认返回false。
3. 子View中如果将传递的事件消费掉,ViewGroup中将无法接收到任何事件。
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值