Android学习笔记042之事件处理机制

news/2024/7/4 1:31:53 标签: android, 对象, class, 事件处理
class="baidu_pl">
class="article_content clearfix">
class="markdown_views prism-atom-one-dark">

  Android提供了两套事件处理机制,分别是:基于监听的事件处理机制和基于回调的事件处理机制。

事件处理机制">基于监听的事件处理机制

事件监听机制由事件源、事件、事件监听器三类class="tags" href="/tags/DuiXiang.html" title=对象>对象组成,基本处理流程如下:

  1. 为某个事件设置一个监听器,监听用户的操作

  2. 用户操作触发了事件源的监听器

  3. 生成事件class="tags" href="/tags/DuiXiang.html" title=对象>对象

  4. 将这个事件源class="tags" href="/tags/DuiXiang.html" title=对象>对象作为参数传递给事件监听器

  5. 事件监听器对事件进行判断,执行对应的事件处理方法

简单的说就是:事件监听机制是一种委派式的事件处理机制,事件源(就是我们的组件,比如Button)将事件处理委托给事件监听器,当事件源发生指定事件时,就通知指定事件监听器,执行相应的逻辑操作。

在Android中,有一下五种基于事件监听的处理形式:

1、匿名内部类作为事件监听器

这是我们最常用的一种方式,直接设置setXxxisntener,重写里面的方法即可,比如:

findViewById(R.id.btn_search_weather).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(MainActivity.this, WeatherActivity.class);
            startActivity(intent);
        }
    });

这种方式比较简单,但是只能单次使用,不能复用

2、内部类作为事件监听器

这个与匿名内部类作为监听器不同,可以重复使用,也可以访问外部类的组件,使用也比较多,比如:

class ButtonClickListener implements View.OnClickListener{

    @Override
    public void onClick(View view) {
        Intent intent = new Intent(MainActivity.this, WeatherActivity.class);
        startActivity(intent);
    }
}

3、外部类作为事件监听器

新建一个类实现相应的事件,这种方式使用比较少,不能访问Activity里面的组件,比如:

package com.example.webservicedemo;

import class="tags" href="/tags/ANDROID.html" title=android>android.view.View;

/**
 * Created by Devin on 2016/8/10.
 */
public class OnButtonClickListener implements View.OnClickListener {
private String content;

public OnButtonClickListener(String content) {
    this.content = content;
}

@Override
public void onClick(View view) {
    //执行操作

}
}

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

直接让Activity实现XxxListener,然后重写里面的方法,组件设置监听为this即可,例如:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    findViewById(R.id.btn_search_phone).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(MainActivity.this, PhoneActivity.class);
            startActivity(intent);
        }
    });


    findViewById(R.id.btn_search_weather).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(MainActivity.this, WeatherActivity.class);
            startActivity(intent);
        }
    });
    findViewById(R.id.btn_handler_ui).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

        }
    });
    findViewById(R.id.btn_handler_son).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(MainActivity.this, SonHandlerActivity.class);
            startActivity(intent);

        }
    });

    findViewById(R.id.btn_search_weather).setOnClickListener(this);
}

//重写onClick方法
@Override
public void onClick(View view) {
    Intent intent = new Intent(MainActivity.this, WeatherActivity.class);
    startActivity(intent);
}

这种方法如果是多个组件同时使用这种监听方式的话需要判断点击的是哪一个组件

5、直接绑定到标签

这种就是直接在XML布局文件中给需要设置监听的组件设置一个class="tags" href="/tags/ANDROID.html" title=android>android:onClick=”监听方法”属性,然后在相应的Activity中实现该方法。

事件处理机制">基于回调的事件处理机制

所谓的回调,在实现具有通用性质的应用架构时非常常见:对于一个具有通用架构的程序来说,程序架构完成整个程序的通用功能、流程,但在某个特定的点上,需要一段业务相关的代码——通用的程序架构无法实现这段代码,那么程序架构会在这个点上留一个“空”。

有两种方式:

  • 以接口形式存在:该接口由开发者实现,实现该接口时会实现该接口的方法,那么通用的程序架构就会调用该方法来完成相关业务的处理。

  • 以抽象方法(也可以说是非抽象方法)的形式存在:这就是Activity的实现形式,这些特定的点上的方法已经被定义了,如onCreate,onActivityResult等方法,开发者可以选择性地重写这些方法,通用的程序架构就会回调这些方法来完成相关业务的处理。

举个简单的例子说明一下事件回调机制:

  张三叫李四去统计公司周末有多少人去聚餐的,但是张三因为有事情需要处理,不能等到李四全部统计完,所以就跟李四做一个约定,统计完了打电话告诉张三。张三跟李四约定了一个接口,张三叫李四统计去聚餐的人数,当李四统计完之后通过这个接口告诉张三周末聚餐的人数,这个就是回调。

Android提供了以下回调方法:

  • onKeyDown (int keyCode, KeyEvent event):用于捕捉手机键盘被按下的事件,返回值是boolean类型,返回true测试自己消费这个事件,false测试不消费这个事件,让其它回调方法处理

  • onKeyUp (int keyCode, KeyEvent event):用于捕捉手机键盘松开事件,返回值也是boolean类型,true表示自己消费这个事件,false测试不消费。

  • onTouchEvent (MotionEvent event):处理手机屏幕触摸事件,返回值同样是boolean类型,true表示自己消费,false表示让其它回调方法处理,这个方法一般处理三个事件:屏幕按下MotionEvent.ACTION_DOWN、屏幕被抬起MotionEvent.ACTION_UP、在屏幕上滑动MotionEvent.ACTION_MOVE

  • onTrackballEvent (MotionEvent event):手机中轨迹球的回调,在所有的View中都有实现,返回值也是boolean类型,与前面介绍的回调方法返回值机制一样。

  • onFocusChanged (boolean gainFocus, int direction, Rect previously FocusedRect) :焦点改变的回调方法,此方法只能在View中实现,返回值类型是void。

与焦点有关的常用方法有:

  • setFocusable方法:设置View是否可以拥有焦点。

  • isFocusable方法:监测此View是否可以拥有焦点。

  • setNextFocusDownId方法:设置View的焦点向下移动后获得焦点View的ID。

  • hasFocus方法:返回了View的父控件是否获得了焦点。

  • requestFocus方法:尝试让此View获得焦点。

  • isFocusableTouchMode方法:设置View是否可以在触摸模式下获得焦点,在默认情况下是不可用获得的。

      在Android中,使用到回调的一般有两种情况:自定义View和基于回调的传播机制。在自定义View中回调使用的比较多,下面我们通过一个例子实现一下:

    package com.example.webservicedemo;

    import class="tags" href="/tags/ANDROID.html" title=android>android.content.Context;
    import class="tags" href="/tags/ANDROID.html" title=android>android.util.AttributeSet;
    import class="tags" href="/tags/ANDROID.html" title=android>android.util.Log;
    import class="tags" href="/tags/ANDROID.html" title=android>android.view.KeyEvent;
    import class="tags" href="/tags/ANDROID.html" title=android>android.view.MotionEvent;
    import class="tags" href="/tags/ANDROID.html" title=android>android.widget.Button;

    /**

    • Created by Devin on 2016/8/10.
      */
      public class AutoButton extends Button {

    private static String TAG = “AutoButton”;

    public AutoButton(Context context) {
    super(context);
    }

    public AutoButton(Context context, AttributeSet attrs) {
    super(context, attrs);
    }

    public AutoButton(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
    Log.i(TAG,”——–>onKeyDown事件被触发”);
    return true;
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
    Log.i(TAG,”——–>onKeyUp事件被触发”);
    return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
    Log.i(TAG,”——–>onTouchEvent事件被触发”);
    return true;
    }
    }

我们重写了Button的三个事件,点击按钮后触发onTouchEvent事件,当我们按模拟器上的键盘时, 按下触发onKeyDown,离开键盘时触发onKeyUp事件。当发生点击事件后就不需要我们在Java文件中进行 事件监听器的绑定就可以完成回调,即组件会处理对应的事件,即事件由事件源(组件)自身处理。

关于事件处理就简单介绍到这里,事件处理主要的核心是了解事件的传播顺序:监听器优先,接着是View本身,最后是Activity,返回值是boolean类型,true的话就是拦截事件传播,自己消费,false测试不拦截事件,让下一层的回调方法处理。


http://www.niftyadmin.cn/n/1167980.html

相关文章

VS历程简单记录

当时一开始装VS2015,是用了很长时间了。装了之后是可以用的,打了不少代码的。 后来很长一段时间没用它了,时隔良久,双击快捷方式竟然打开不了,让我“重装”。 其实也不用重装,本机用的Win10,去控…

【随笔】野生在左 科班在右——数据结构学习誓师贴

一. 科班 Vs 野生 这个老生常谈的问题让很多野生码农觉得不公平,在一次次面试中因为学历和那些工作中根本就用不到的知识虐的一脸懵逼,然后除了抱怨什么也做不了。那为什么看起来很多科班同学的编码水平和职场软技能都不如野生码农的逆风局中&#xff0c…

解析RocketMQ的消息索引文件consumequeue

CommitLog的文件结构 下图展示了CommitLog的文件结构,可以看到,包含了topic、queueId、消息体等核心信息。 同Kafka一样,消息是变长的,顺序写入。 如下图所示: ConsumeQueue的文件结构 ConsumeQueue中并不需要存储消息…

几个类的内置方法

# 类的内置方法# 双下方法# __str__# 当类中定义了__str__方法后,print(这个类对象时),会调用__str__. 或者格式化%s输出对象时,都会触发__str__# __repr__# 当类中定义了__repr__方法后,print(repr(a)),就会调用a对象中的__repr_…

AndroidASD完全解析04之Snackbar

前面我们介绍过了NavigationView、TextInputLayout和FloatingActionButton这个三个控件,有兴趣的可以猛戳了解:AndroidASD完全解析01之NavigationView AndroidASD完全解析02之TextInputLayout 、AndroidASD完全解析03之FloatingActionButton&#xff0c…

【C入门篇】[1] windows下的IDE - building

【C入门篇】[1] windows下的IDE - building author : MinRam(minfysuigmail.com)create : 2018/10/03update: 2018/10/03前言 工欲善其事, 必先利其器本文如有不足或错误,欢迎指出 : ) 书籍推荐 《C Primer Plus》:公认教程《狂人学C》 &…

一图胜千言 - 查看态势感知日志分析内置9大报表

背景 目前,阿里云态势感知与日志服务打通,对外开放平台依赖或者产生的日志,包括网络、主机、安全三大类共14种子类日志。提供近实时的日志自动采集存储、并提供基于日志服务的查询分析、报表报警、下游计算对接与投递的能力。 本文介绍如何在…

AndroidASD完全解析01之NavigationView

在2015年GoogleIO大会上,Google除了推出Android L之外,还推出了一个全新的支持库Android Support Design Library,这个库给我们提供了8个具有规范的Merterial Design风格控件。这8个控件分别是:NavigationView,TextIn…