您的位置:首页 > 职场人生

个人总结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本身调用这个方法要求parent
view重新调用他的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 Fragment