个人总结Android面试题目之二
2013-12-09 17:11
507 查看
1.Andriod中onTouchEvent(),onInterceptTouchEvent(),onDispatchEvent()区别
onDispatchEvent:分发事件onTouchEvent:触发触摸事件
onInterceptTouchEvent:触发拦截触摸事件
onInterceptTouchEvent:是定义于ViewGroup里面的一个方法,此事件是用于拦截触摸事件的,ViewGroup(继承自View),一个View的Group,也就是我们的一个布局如LinerLayout,各个布局类都继承自ViewGroup;
onTouchEvent:是定义于View中的一个方法,处理传递到View的手势触摸事件。手势事件类型包括ACTION_DOWN,ACTION_MOVE,ACTION_UP,ACTION_CANCEL等事件;
其中ViewGroup里的onInterceptTouchEvent默认返回值是false,这样touch事件会传递到View控件,ViewGroup里的onTouchEvent默认返回值是false;
View里的onTouchEvent默认返回值是true,当我们手指点击屏幕时候,先调用ACTION_DOWN事件,当onTouchEvent里返回值是true的时候,onTouch会继续调用ACTION_UP事件,如果onTouchEvent里返回值是false,那么onTouchEvent只会调用ACTION_DOWN而不调用ACTION_UP。
当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、新建两个类LLayout , LView 如下
复制代码代码如下:
public class LLayout extends FrameLayout {
// ViewGroup
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.i("LTAG", "LLayout onInterceptTouchEvent");
Log.i("LTAG", "LLayout onInterceptTouchEvent default return" + super.onInterceptTouchEvent(ev));
return super.onInterceptTouchEvent(ev);
}
// View
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i("LTAG", "LLayout onTouchEvent");
Log.i("LTAG", "LLayout onTouchEvent default return" + super.onTouchEvent(event));
return super.onTouchEvent(event);
}
}
public class LView extends Button {
// TextView <-- View
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i("LTAG", "onTouchEvent");
Log.i("LTAG", "onTouchEvent default return" + super.onTouchEvent(event));
return super.onTouchEvent(event);
}
}
2、修改布局文件为如下布局
复制代码代码如下:
<com.touchpro.LLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.touchpro.LView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/app_name" />
</com.touchpro.LLayout>
(1)先点击界面中的按钮
(2)再点击界面中的其它区域
结论:LLayout 中 onInterceptTouchEvent 默认返回值为false,onTouchEvent 默认返回值为false,所以只调用了ACTION_DOWN事件;
LView中 onTouchEvent 默认返回值为true;调用了ACTION_DOWN,ACTION_UP 两个事件;
(3)修改LLayout中onInterceptTouchEvent返回值为true,再次运行代码:
结论:LLayout中onInterceptTouchEvent返回了true,对触摸事件进行了拦截,所以没有将事件传递给View,而直接执行了LLayout中的onTouchEvent事件;
(4)把LLayout中onInterceptTouchEvent返回值改为false,再把LView中的onTouchEvent改为返回false:
结论:由于将LView中onTouchEvent返回值修改为false,因此只执行了ACTION_DOWN,然后就到LLayout中执行onTouchEvent事件了;
ViewGroup里的onInterceptTouchEvent默认值是false这样才能把事件传给View里的onTouchEvent.
ViewGroup里的onTouchEvent默认值是false。
View里的onTouchEvent返回默认值是true.这样才能执行多次touch事件。
2.Fragment生命周期
Fragment与Activity生命周期对比图:
1.当一个Fragment被创建的时候会经历以下生命周期
onAttach()
onCreate()
onCreateView()
onActivityCreated()
2. 当这个fragment对用户可见的时候,它会经历以下状态。
onStart()
onResume()
3. 当这个fragment进入“后台模式”的时候,它会经历以下状态。
onPause()
onStop()
4. 当这个fragment被销毁了(或者持有它的activity被销毁了),它会经历以下状态。
onPause()
onStop()
onDestroyView()
onDestroy() // 本来漏掉类这个回调,感谢xiangxue336提出。
onDetach()
5. 就像activitie一样,在以下的状态中,可以使用Bundle对象保存一个fragment的对象。
onCreate()
onCreateView()
onActivityCreated()
6. fragments的大部分状态都和activitie很相似,但fragment有一些新的状态。
onAttached() —— 当fragment被加入到activity时调用(在这个方法中可以获得所在的activity)。
onCreateView() —— 当activity要得到fragment的layout时,调用此方法,fragment在其中创建自己的layout(界面)。
onActivityCreated() —— 当activity的onCreated()方法返回后调用此方法
onDestroyView() —— 当fragment中的视图被移除的时候,调用这个方法。
onDetach() —— 当fragment和activity分离的时候,调用这个方法。
一旦activity进入resumed状态(也就是running状态),你就可以自由地添加和删除fragment了。因此,只有当activity在resumed状态时,fragment的生命周期才能独立的运转,其它时候是依赖于activity的生命周期变化的。
3.abstact class和interface的区别
抽象类: |-由抽象方法和常量、变量、全局常量、构造方法、普通方法组成 |-使用abstract声明 |-子类要通过extends继承抽象类,子类如果不是抽象类,则必须覆写抽象类的全部抽象方法 |-存在单继承的局限 |-抽象类可以实现若干个接口 接口: |-由抽象方法和全局常量组成 |-使用interface关键字 |-子类要通过implements实现接口,子类如果不是抽象类,则必须覆写抽象类的全部抽象方法 |-一个子类可以实现多个接口 |-接口不能继承一个抽象类,但允许继承多个接口
接口缺点:如果向一个java接口加入一个新的方法时,所有实现这个接口的类都得编写具体的实现。 接口优点:一个类可以实现多个接口,接口可以让这个类不仅具有主类型的行为,而且具有其他的次要行为,比如 HashMap主要类型是Map,而Cloneable接口使它具有一个次要类型,这个类型说明它可以安全的克隆. 抽象类的缺点:一个类只能由一个超类继承,所以抽象类作为类型定义工具的效能大打折扣。 抽象类的优点:具体类可从抽象类自动得到这些方法的缺省实现。
4.ArrayList,Vector,LinkedList存储性能和特性
ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,
Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差。
LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
5.Service的几种启动方式和区别,IntentService和Service的区别
官方给出的两种服务的生命周期图:左图表示的是startService启动方式,右图表示的是bindService启动方式
使用context.startService() 启动Service
其生命周期为context.startService() ->onCreate()- >onStart()->Service running-->context.stopService() | ->onDestroy() ->Service stop
如果Service还没有运行,则android先调用onCreate()然后调用onStart();
如果Service已经运行,则只调用onStart(),所以一个Service的onStart方法可能会重复调用多次。
stopService的时候直接onDestroy,
如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。
该Service的调用者再启动起来后可以通过stopService关闭Service。
所以调用startService的生命周期为:onCreate --> onStart(可多次调用) --> onDestroy
对于bindService()启动Service会经历:
context.bindService()->onCreate()->onBind()->Service running-->onUnbind() -> onDestroy() ->Service stop
onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。
这个时候把调用者(Context,例如Activity)会和Service绑定在一起,Context退出了,
Srevice就会调用onUnbind->onDestroy相应退出。
所以调用bindService的生命周期为:onCreate --> onBind(只一次,不可多次绑定) --> onUnbind --> onDestory。
一但销毁activity它就结束,如果按home把它放到后台,那他就不退出。
IntentService相对于Service来说,有几个非常有用的优点:
IntentService使用队列的方式将请求的Intent加入队列,然后开启一个worker thread(线程)来处理队列中的Intent,对于异步的startService请求,IntentService会处理完成一个之后再处理第二个,每一个请求都会在一个单独的worker
thread中处理,不会阻塞应用程序的主线程,这里就给我们提供了一个思路,如果有耗时的操作与其在Service里面开启新线程还不如使用IntentService来处理耗时操作。
详见:http://blog.csdn.net/zhf198909/article/details/6906786
6.Service通信的几种方式,跨进程通信和同进程通信的不同。
通过Binder对象当Activity通过调用bindService(Intent service, ServiceConnection conn,int flags),我们可以得到一个Service的一个对象实例,然后我们就可以访问Service中的方法。。。
通过broadcast(广播)的形式
当我们的进度发生变化的时候我们发送一条广播,然后在Activity的注册广播接收器,接收到广播之后更新UI线程。。。。
详见:http://blog.csdn.net/xiaanming/article/details/9750689
跨进程通信 Android四种实现方式
详见:http://blog.csdn.net/toyuexinshangwan/article/details/8640709
LruCache缓存图片
转载:http://blog.csdn.net/xiaanming/article/details/9825113
图片压缩例子
转载:http://my.eoe.cn/isnull/archive/564.html
三种压缩方法:http://www.jb51.net/article/41117.htm
7.使用Memory
Analyzer Tool(MAT)Eclipse插件分析内存泄露
详见博客:http://blog.csdn.net/jl_qiqi/article/details/8572825
//Eclipse MAT 工具的使用(a)
http://blog.csdn.net/jl_qiqi/article/details/8572945 //MAT分析内存泄露
8.Invalidate,postInvalidate,requestLayout区别
requestLayout:当view确定自身已经不再适合现有的区域时,该view本身调用这个方法要求parentview重新调用他的onMeasure onLayout来对重新设置自己位置。
特别的当view的layoutparameter发生改变,并且它的值还没能应用到view上,这时候适合调用这个方法
Android中实现view的更新有两组方法,一组是invalidate,另一组是postInvalidate,其中前者是在UI线程自身中使用,而后者在非UI线程中使用。
Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用。
Android程序中可以使用的界面刷新方法有两种,分别是利用Handler和利用postInvalidate()来实现在线程中刷新界面。
1,利用invalidate()刷新界面
实例化一个Handler对象,并重写handleMessage方法调用invalidate()实现界面刷新;而在线程中通过sendMessage发送界面更新消息。
2,使用postInvalidate()刷新界面
使用postInvalidate则比较简单,不需要handler,直接在线程中调用postInvalidate即可。
9.JAVA多线程,线程之间的通信
线程间通信主要用wait(),notify()方法来实现,详细见下面的博客。http://www.cnblogs.com/mengdd/archive/2013/02/20/2917956.html
相关文章推荐
- 个人总结Android面试题目之一
- Android面试题目总结
- 面试大总结之二:Java搞定面试中的二叉树题目
- Android面试之个人总结
- Android面试常见题目总结(1)
- Android 面试精华题目总结
- Android个人面试总结
- 面试大总结之二:Java搞定面试中的二叉树题目
- Android面试题目总结
- Android 面试精华题目总结
- Android 面试精华题目总结
- 【Linux】Linux 个人面试题目总结
- Android 面试题目总结(1)
- Android 面试精华题目总结
- 2011.9.27到某公司的Android面试(C/java/Android)题目总结
- Android 面试精华题目总结
- [置顶] Android面试题目之二:整形转换为字符串
- Android 面试题目总结【持续更新...】
- Android 面试精华题目总结
- Android 面试精华题目总结