请简述什么是android事件处理,并分析两种android事件处理机制的实现过程...
发布网友
发布时间:2022-04-26 18:01
我来回答
共3个回答
热心网友
时间:2022-04-22 09:42
UI编程通常都会伴随事件处理,Android也不例外,它提供了两种方式的事件处理:基于回调的事件处理和基于*的事件处理。
对于基于*的事件处理而言,主要就是为Android界面组件绑定特定的事件*;对于基于回调的事件处理而言,主要做法是重写Android组件特定的回调函数,Android大部分界面组件都提供了事件响应的回调函数,我们主要重写它们就行。
一 基于*的事件处理
相比于基于回调的事件处理,这是更具“面向对象”性质的事件处理方式。在*模型中,主要涉及三类对象:
1)事件源Event Source:产生事件的来源,通常是各种组件,如按钮,窗口等。
2)事件Event:事件封装了界面组件上发生的特定事件的具体信息,如果*需要获取界面组件上所发生事件的相关信息,一般通过事件Event对象来传递。
3)事件*Event Listener:负责监听事件源发生的事件,并对不同的事件做相应的处理。
基于*的事件处理机制是一种委派式Delegation的事件处理方式,事件源将整个事件委托给事件*,由*对事件进行响应处理。这种处理方式将事件源和事件*分离,有利于提供程序的可维护性。
举例:
View类中的OnLongClickListener*定义如下:(不需要传递事件)
[java] view plaincopyprint?
public interface OnLongClickListener {
boolean onLongClick(View v);
}
public interface OnLongClickListener {
boolean onLongClick(View v);
}
View类中的OnLongClickListener*定义如下:(需要传递事件MotionEvent)
[java] view plaincopyprint?
public interface OnTouchListener {
boolean onTouch(View v, MotionEvent event);
}
public interface OnTouchListener {
boolean onTouch(View v, MotionEvent event);
}
二 基于回调的事件处理
相比基于*的事件处理模型,基于回调的事件处理模型要简单些,该模型中,事件源和事件*是合一的,也就是说没有独立的事件*存在。当用户在GUI组件上触发某事件时,由该组件自身特定的函数负责处理该事件。通常通过重写Override组件类的事件处理函数实现事件的处理。
举例:
View类实现了KeyEvent.Callback接口中的一系列回调函数,因此,基于回调的事件处理机制通过自定义View来实现,自定义View时重写这些事件处理方法即可。
[java] view plaincopyprint?
public interface Callback {
// 几乎所有基于回调的事件处理函数都会返回一个boolean类型值,该返回值用于
// 标识该处理函数是否能完全处理该事件
// 返回true,表明该函数已完全处理该事件,该事件不会传播出去
// 返回false,表明该函数未完全处理该事件,该事件会传播出去
boolean onKeyDown(int keyCode, KeyEvent event);
boolean onKeyLongPress(int keyCode, KeyEvent event);
boolean onKeyUp(int keyCode, KeyEvent event);
boolean onKeyMultiple(int keyCode, int count, KeyEvent event);
}
public interface Callback {
// 几乎所有基于回调的事件处理函数都会返回一个boolean类型值,该返回值用于
// 标识该处理函数是否能完全处理该事件
// 返回true,表明该函数已完全处理该事件,该事件不会传播出去
// 返回false,表明该函数未完全处理该事件,该事件会传播出去
boolean onKeyDown(int keyCode, KeyEvent event);
boolean onKeyLongPress(int keyCode, KeyEvent event);
boolean onKeyUp(int keyCode, KeyEvent event);
boolean onKeyMultiple(int keyCode, int count, KeyEvent event);
}
三 比对
基于*的事件模型符合单一职责原则,事件源和事件*分开实现;
Android的事件处理机制保证基于*的事件处理会优先于基于回调的事件处理被触发;
某些特定情况下,基于回调的事件处理机制会更好的提高程序的内聚性。
四 基于自定义*的事件处理流程
在实际项目开发中,我们经常需要自定义*来实现自定义业务流程的处理,而且一般都不是基于GUI界面作为事件源的。这里以常见的app自动更新为例进行说明,在自动更新过程中,会存在两个状态:下载中和下载完成,而我们的程序需要在这两个状态做不同的事情,“下载中”需要在UI界面上实时显示软件包下载的进度,“下载完成”后,取消进度条的显示。这里进行一个模拟,重点在说明自定义*的事件处理流程。
4.1)定义事件*如下:
热心网友
时间:2022-04-22 11:00
Android事件处理的两种模型
UI编程通常都会伴随事件处理,Android也不例外,它提供了两种方式的事件处理:基于回调的事件处理和基于*的事件处理。
对于基于*的事件处理而言,主要就是为Android界面组件绑定特定的事件*;对于基于回调的事件处理而言,主要做法是重写Android组件特定的回调函数,Android大部分界面组件都提供了事件响应的回调函数,我们主要重写它们就行。
一 基于*的事件处理
相比于基于回调的事件处理,这是更具“面向对象”性质的事件处理方式。在*模型中,主要涉及三类对象:
1)事件源Event Source:产生事件的来源,通常是各种组件,如按钮,窗口等。
2)事件Event:事件封装了界面组件上发生的特定事件的具体信息,如果*需要获取界面组件上所发生事件的相关信息,一般通过事件Event对象来传递。
3)事件*Event Listener:负责监听事件源发生的事件,并对不同的事件做相应的处理。
基于*的事件处理机制是一种委派式Delegation的事件处理方式,事件源将整个事件委托给事件*,由*对事件进行响应处理。这种处理方式将事件源和事件*分离,有利于提供程序的可维护性。
举例:
View类中的OnLongClickListener*定义如下:(不需要传递事件)
public interface OnLongClickListener {
boolean onLongClick(View v);
}
View类中的OnLongClickListener*定义如下:(需要传递事件MotionEvent)
public interface OnTouchListener {
boolean onTouch(View v, MotionEvent event);
}
二 基于回调的事件处理
相比基于*的事件处理模型,基于回调的事件处理模型要简单些,该模型中,事件源和事件*是合一的,也就是说没有独立的事件*存在。当用户在GUI组件上触发某事件时,由该组件自身特定的函数负责处理该事件。通常通过重写Override组件类的事件处理函数实现事件的处理。
举例:
View类实现了KeyEvent.Callback接口中的一系列回调函数,因此,基于回调的事件处理机制通过自定义View来实现,自定义View时重写这些事件处理方法即可。
public interface Callback {
// 几乎所有基于回调的事件处理函数都会返回一个boolean类型值,该返回值用于
// 标识该处理函数是否能完全处理该事件
// 返回true,表明该函数已完全处理该事件,该事件不会传播出去
// 返回false,表明该函数未完全处理该事件,该事件会传播出去
boolean onKeyDown(int keyCode, KeyEvent event);
boolean onKeyLongPress(int keyCode, KeyEvent event);
boolean onKeyUp(int keyCode, KeyEvent event);
boolean onKeyMultiple(int keyCode, int count, KeyEvent event);
}
三 比对
基于*的事件模型符合单一职责原则,事件源和事件*分开实现;
Android的事件处理机制保证基于*的事件处理会优先于基于回调的事件处理被触发;
某些特定情况下,基于回调的事件处理机制会更好的提高程序的内聚性。
四 基于自定义*的事件处理流程
在实际项目开发中,我们经常需要自定义*来实现自定义业务流程的处理,而且一般都不是基于GUI界面作为事件源的。这里以常见的app自动更新为例进行说明,在自动更新过程中,会存在两个状态:下载中和下载完成,而我们的程序需要在这两个状态做不同的事情,“下载中”需要在UI界面上实时显示软件包下载的进度,“下载完成”后,取消进度条的显示。这里进行一个模拟,重点在说明自定义*的事件处理流程。
4.1)定义事件*如下:
public interface DownloadListener {
public void onDownloading(int progress); //下载过程中的处理函数
public void onDownloaded(); //下载完成的处理函数
}
4.2)实现下载操作的工具类代码如下:
public class DownloadUtils {
private static DownloadUtils instance = null;
private DownloadUtils() {
}
public static synchronized DownloadUtils instance() {
if (instance == null) {
instance = new DownloadUtils();
}
return instance;
}
private boolean isDownloading = true;
private int progress = 0;
// 实际开发中这个函数需要传入url作为参数,以获取服务器端的安装包位置
public void download(DownloadListener listener) throws InterruptedException {
while (isDownloading) {
listener.onDownloading(progress);
// 下载过程的简单模拟
Thread.sleep(1000);
progress += 10;
if (progress >= 100) {
isDownloading = false;
}
}
// 下载完成
listener.onDownloaded();
}
}
4.3)最后在main函数中模拟事件源:
public class DownloadUI {
public static void main(String[] args) {
try {
DownloadUtils.instance().download(new MyDownloadListener());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static class MyDownloadListener implements DownloadListener {
@Override
public void onDownloading(int progress) {
System.out.println("下载进度是:" + progress);
}
@Override
public void onDownloaded() {
System.out.println("下载完成");
}
}
}
热心网友
时间:2022-04-22 12:35
1.监听事件处理
基于监听的事件处理分工明确,可维护性高,且会优先触发。
内部类形式:Class MyClickListener implements View.OnClickListener{ 实现的方法,即事件处理器}
外部类形式:将事件*类定义成一个外部类:public class SendSmsListener implements OnLongClickListener{容易把业务逻辑和显示逻辑耦合,不利于程序的内聚性:p195}
Activity本身作为事件*:让Activity本身实现*接口,并实现处理方法。做法简洁,Activity本身应该完成界面的初始化工作,同时包含事件处理比较混乱。public
匿名内部类形式:btn.setOnClickListener( new OnClickListener(){ 实现时间的处理方法 });
绑定到标签:在XML未指定标签绑定事件处理方法,android:onClick = "clickHandler",写一个clickHandler(){ 处理 }方法。
2.回调事件处理
监听事件处理是委托式处理,回调事件处理是实现组件自己特定的方法来处理事件,没有监听事件。
public MyButton extends Button{
public boolean onKeyDown(int KeyCode,KeyEvent event){
super.onKeyDown(KeyCode,event);
Log.v("返回值","true不会向外扩散");
return true;
}
}
MyButton重写了父类的onKeyDown()方法,不需要绑定监听,自己会处理相应的事件。
回调方法的返回值为true表示能完全处理,不会传播出去。返回false,表示未完全处理,会传播出去。 如果没有完成处理(false),则由*-->事件回调-->传播到activity,都会出发该方法处理。
3.相应系统设置的事件
Configuration类专门用于描述手机上配置信息,包括用户特定配置和系统动态配置。
Configuration cfg = getResources().getConfiguration();获取了Configuration对象可以使用该对象提供的属性来获取系统配置。
4.Handler消息传递机制
主线程又称为UI线程,在主线程不进行耗时操作,这是需要用到handler。耗时操作会引发ANR异常。
Handler类主要有两个作用:在新启动的线程中发送消息至MessageQueue ;在主线程中获取Looper分给他的消息,处理消息。
Looper :每个线程只能拥有一个looper ,负责管理MessageQueue,不断从消息队列中取出消息,分给对应的Handler处理。
MessageQueue :消息队列,采取先进先出的方式管理message。
HandlerMessage() :Handler接收和处理的消息对象。
在主线程中,系统已经初始化了一个Looper对象,因此程序直接创建Handler并收发消息即可;而自己启动的子线程,必须自己创建一个Looper对象并启动它:Looper.prepare() 创建对象并保证只有一个Looper对象。
Android不允许在子线程中更改UI组件,需要在子线程中更改界面组件必须用handler实现。
5.异步任务
实现异步任务的机制有两种:Handler和AsyncTask。
AsyncTask<Params,Progress,Result>
三种泛型类型分别代表“启动任务执行的输入参数”、“后台任务执行的进度”、“后台计算结果的类型”。在特定场合下,并不是所有类型都被使用,如果没有被使用,可以用java.lang.Void类型代替。
一个异步任务的执行一般包括以下几个步骤:
1.execute(Params... params),执行一个异步任务,需要我们在代码中调用此方法,触发异步任务的执行。
2.onPreExecute(),在execute(Params... params)被调用后立即执行,一般用来在执行后台任务前对UI做一些标记。
3.doInBackground(Params... params),在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。
4.onProgressUpdate(Progress... values),在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。
5.onPostExecute(Result result),当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。
在使用的时候,有几点需要格外注意:
1.异步任务的实例必须在UI线程中创建。
2.execute(Params... params)方法必须在UI线程中调用。
3.不要手动调用onPreExecute(),doInBackground(Params... params),onProgressUpdate(Progress... values),onPostExecute(Result result)这几个方法。
4.不能在doInBackground(Params... params)中更改UI组件的信息。
5.一个任务实例只能执行一次,如果执行第二次将会抛出异常。