Android事件处理

Android有两套事件处理机制:

1.    基于监听的事件处理

2.    基于回调的事件处理

一、  基于监听的事件处理

是一种基于委托式(Delegation)的事件处理方式。

1、        内部类的形式

2、        匿名类的形式

3、        直接绑定到标签

4、        外部类的形式

5、        Activity本身作为事件监听器

其中前三种较为好用,后两种不常用。

1、2大家都很熟悉了。

3举个例子:在Button标签里写一行代码:android:onClick=”clickHandler”,在该布局对应的Activity里定义一个void clickHandler(View source)方法即可。

4使用外部类的话,有两个缺点:

1、        事件监听器通常属于特定的GUI界面,定义成外部类不利于提高程序的内聚性。

2、        外部类形式的事件监听器不能自由访问创建GUI界面的类中的组件,编程不够简洁。此时需要在此外部类的方法里传递Activity、View作为参数才行。

5的话:

1、        Activity的主要职责是完成界面初始化,但此时还有包含事件处理方法,有点混乱。

2、        如果Activity界面类还要实现监听器接口(implements OnClickListener),让人觉得有点怪异。

二、  基于回调的事件处理

对于基于回调的事件处理模型来说,事件源与事件监听器是统一的,或者说事件监听器完全消失了。当用户在GUI组件上激发某个事件是,组件自己特定的方法将会负责处理该事件。举个例子:

类文件:

public class MyButton extends Button
{
      publicMyButton(Context context , AttributeSet set)
      {
           super(context, set);
      }
      @Override
      publicboolean onKeyDown(int keyCode, KeyEvent event)
      {
           super.onKeyDown(keyCode, event);
           Log.v("-crazyit.org-","the onKeyDown in MyButton");
           //返回true,表明该事件不会向外扩散
           returntrue;
}


布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                   android:orientation="vertical"
                   android:layout_width="match_parent"
                  android:layout_height="match_parent">
      <!--使用自定义View时应使用全限定类名 -->
      <org.crazyit.event.MyButton
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:text="单击我"/>
</LinearLayout>


基于回调的事件传播:

Android系统最先触发的是该按键上绑定的事件监听器,接着触发该组件提供的事件回调方法,然后还会传播到该组件所在的Activity

public class MyButton extends Button
{
      publicMyButton(Context context , AttributeSet set)
      {
           super(context, set);
      }
      @Override
      publicboolean onKeyDown(int keyCode, KeyEvent event)
      {
           super.onKeyDown(keyCode, event);
           Log.v("-MyButton-","the onKeyDown in MyButton");             //第二个触发
           //返回false,表明并未完全处理该事件,该事件依然向外扩散
           returnfalse;
      }
}


public class MainActivity extends Activity
{
      @Override
      publicvoid onCreate(Bundle savedInstanceState)
      {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.main);
           Buttonbn = (Button) findViewById(R.id.bn);
           //为bn绑定事件监听器
           bn.setOnKeyListener(newOnKeyListener() {
                 @Override
                 publicboolean onKey(View source
                            ,int keyCode, KeyEvent event) {
                      //只处理按下键的事件
                      if(event.getAction() == KeyEvent.ACTION_DOWN) {
                            Log.v("-Listener-","the onKeyDown in Listener");
                      }
                      //返回false,表明该事件会向外传播
                      returntrue; // 第①个触发
                 }
           });
      }
      //重写onKeyDown方法,该方法可监听它所包含的所有组件的按键被按下事件
      @Override
      publicboolean onKeyDown(int keyCode, KeyEvent event)
      {
           super.onKeyDown(keyCode, event);
           Log.v("-Activity-", "the onKeyDown in Activity");
           //返回false,表明并未完全处理该事件,该事件依然向外扩散
           returnfalse;//第三个触发
      }
}


三、  响应的系统设置的事件

可使用Configurationcfg = getResourses().getConfiguration();来获取系统的Configuration对象。

如果要使程序自动响应系统设置更改,需要重写Activity的onConfigurationChanged(Configuration neConfig)方法,该方法可用于监听系统设置的更改。

四、Handler消息传递机制

由于Android不允许在子线程中更新界面组件,如果想在子线程中更新界面组件,开发者需要借助于Handler对象来实现。

Handler类的主要作用有两个:

1、        在新启动的线程中发送消息。

2、        在主线程中获取、处理消息。

举个例子:

public class MainActivity extends Activity
{
      //定义周期性显示的图片的ID
      int[]imageIds = new int[]
           {
                 R.drawable.java,
                 R.drawable.javaee,
                 R.drawable.ajax,
                 R.drawable.android,
                 R.drawable.swift
           };
      intcurrentImageId = 0;
      @Override
      publicvoid onCreate(Bundle savedInstanceState)
      {
           super.onCreate(savedInstanceState);
           setContentView(R.layout.main);
           finalImageView show = (ImageView) findViewById(R.id.show);
           finalHandler myHandler = new Handler()
           {
                 @Override
                 publicvoid handleMessage(Message msg)
                 {
                      //如果该消息是本程序所发送的
                      if(msg.what == 0x1233)
                      {
                            //动态地修改所显示的图片
                            show.setImageResource(imageIds[currentImageId++
                                       %imageIds.length]);
                      }
                 }
           };
           //定义一个计时器,让该计时器周期性地执行指定任务
           newTimer().schedule(new TimerTask()
           {
                 @Override
                 publicvoid run()
                 {
                      //发送空消息
                      myHandler.sendEmptyMessage(0x1233);
                 }
           },0, 1200);
      }
}


 

 

 

posted @ 2016-06-17 14:28  StevenLuke  阅读(160)  评论(0编辑  收藏  举报