Android 事件处理探险

Android 事件处理探险,第1张

概述Android提供了两套事件处理机制:基于监听的事件处理;基于回调的事件处理1.基于监听的事件处理Android的事件处理是一种委派式事件处理方式(事件源将整个事件处理委托给事件监听器),事件监听的处理模型主要涉及:EventSource(事件源)、Event(事件)、EventListener(事件监听器)。小技巧:requestW

AndroID提供了两套事件处理机制:基于监听的事件处理;基于回调的事件处理

1.基于监听的事件处理

AndroID的事件处理是一种委派式事件处理方式(事件源将整个事件处理委托给事件监听器),事件监听的处理模型主要涉及:Event Source(事件源)、Event(事件)、Event Listener(事件监听器)。

小技巧:requestwindowFeature(Window.FEATURE_NO_Title); // 去掉窗口标题getwindow().setFlags(WindowManager.LayoutParams.FLAG_FulLSCREEN,WindowManager.LayoutParams.FLAG_FulLSCREEN); // 全屏显示

在基于监听的事件处理模型中,事件监听器必须实现事件监听器接口(通常以内部类的形式存在),以VIEw为例,提供了如下几个接口:

VIEw.OnClickListener    // 单击事件VIEw.OnCreateContextMenuListener    // 创建上下文菜单事件VIEw.OnFocuschangelistener    // 焦点改变事件VIEw.OnKeyListener    // 按钮事件VIEw.OnLongClickListener    // 长点击事件VIEw.OntouchListener    // 触摸屏事件

注意:不推荐将业务逻辑实现写在事件监听器中,包含业务逻辑的事件监听器将导致程序的显示逻辑与业务逻辑耦合,增加了后期维护难度。

2.基于回调的事件处理

AndroID事件处理的回调方法,以VIEw为例,VIEw类包含如下方法:

boolean onKeyDown(int keyCode, KeyEvent event)    // 按下boolean onKeyLongPress(int keyCode, KeyEvent event)    // 长按boolean onKeyUp(int keyCode, KeyEvent event)    // 松开boolean onKeyShortcut(int keyCode, KeyEvent event)        // 键盘快捷键触发时boolean ontouchEvent(MotionEvent event)        // 触摸屏事件

基于回调的事件处理机制可通过自定义view来实现,自定义view时重写该VIEw的事件处理方法即可。
对比AndroID提供了两套事件处理机制,基于监听的事件处理更有优势:可维护性高、保证监听的事件监听器会被优先触发。
基于回调的事件处理更适合于那些比较固定的VIEw。

3.事件传递

所有基于回调的事件处理的回调方法返回true,表明已处理完成,不会继续传递;返回false,表明未处理完成,该事件继续传递下去。

button bn = (button) findVIEwByID(R.ID.bn);// 为bn绑定事件监听器bn.setonKeyListener(new OnKeyListener() {    @OverrIDe    public boolean onKey(VIEw source, int keyCode, KeyEvent event) {        // 只处理按下键的事件        if (event.getAction() == KeyEvent.ACTION_DOWN) {            Log.v("-Listener-", "the onKeyDown in Listener");        }        return true;  // 返回true,表明该事件不会向外传递    }});

当某个键被按下时候,AndroID最先触发的是该按键上绑定的事件监听器,然后触发该组件提供的事件回调方法,最后传递到该组件所在的Activity。

4.响应系统设置的事件

1)Configuration类
专门用于描述手机设备上的配置信息
获取系统的Configuration对象:

Configuration cfg = getResources().getConfiguration();

2)重写onConfigurationChanged方法可以响应系统设置更改

5.Handler消息传递机制

Handler类的主要机制有两个:在子线程中发送消息;在主线程中获取处理消息。
Handler包含如下方法用于发送处理消息:

voID handleMessage(Message msg):处理消息final boolean hasMessages(int what, Object object):检查消息队列中是否包含what属性为指定值且object属性为指定对象的消息boolean sendEmptyMessage(int what):发送空消息boolean sendEmptyMessageDelayed(int what, long delayMillis):延迟发送空消息boolean sendMessage(Message msg):发送消息boolean sendMessageDelayed(Message msg, long delayMillis):延迟发送消息
6.Handler、Looper、MessageQueue

Handler、Looper、MessageQueue各自作用如下:
Handler:能发送消息给MessageQueue,并能处理Looper分发给它的消息;
Looper:每个线程只有一个Looper,负责管理MessageQueue,从MessageQueue中取出消息分发给对应的Handler;
MessageQueue:采用先进先出管理Message;

注意:避免在主线程中执行耗时 *** 作,否则会引发ANR异常。

public class MainActivity extends Activity {    EditText etNum;    ChildThread childThread;    @OverrIDe    public voID onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentVIEw(R.layout.main);        // ...        ChildThread = new ChildThread();        childThread.start();    }    /**     * 定义一个线程类     */     class ChildThread extends Thread {        public Handler mHandler;        public voID run() {            Looper.prepare(); // 创建Looper对象            mHandler = new Handler() {                // 定义处理消息的方法                @OverrIDe                public voID handleMessage(Message msg) {                    if(msg.what == 1) {                        // 执行 *** 作                        // ...                    }                }            };            Looper.loop(); // 启动Looper        }    }    /**     * 按钮的点击事件     */     public voID down(VIEw vIEw) {        Message msg = new Message(); // 创建消息        msg.what = 1;        Bundle bundle = new Bundle();        // num = ...        bundle.putInt("num" ,num);        msg.setData(bundle);        childThread.mHandler.sendMessage(msg); // 向新线程中的Handler发送消息    }}

AndroID为了解决子线程不能更新UI组件的问题,已提供了如下解决方案:

使用Handler实现线程间通信runOnUiThread方法VIEw.post方法VIEw.postDelayed方法

用法如下:

/** * 1.使用Handler实现线程间通信的用法 */public class MainActivity extends Activity {    protected static final int MSG_ONE = 1;    protected static final int MSG_TWO = 2;    private Handler handler = new Handler() {        public voID handleMessage(Message msg) {            switch (msg.what) {                case MSG_ONE:                    // 执行1的 *** 作                    break;                case MSG_TWO:                    // 执行2的 *** 作                    break;            };        }    };    @OverrIDe    protected voID onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentVIEw(R.layout.activity_main);        // 耗时 *** 作要在子线程中 *** 作        new Thread() {            public voID run() {                Message message = Message.obtain(); //获取消息的载体                if (condition) {                    message.what = MSG_ONE;                } else {                    message.what = MSG_TWO;                }                handler.sendMessage(message);            };        }.start();    }}/** * 2.runOnUiThread方法的用法 */public class MainActivity extends Activity {    @OverrIDe    protected voID onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentVIEw(R.layout.activity_main);        // 耗时 *** 作要在子线程中 *** 作        new Thread() {            public voID run() {                //执行耗时 *** 作                //更新主线程UI                runOnUiThread(new Runnable() {                    @OverrIDe                    public voID run() {                    }                });            };        }.start();    }}
7.异步加载(AsyncTask)

1)先自己手写一个异步加载框架,其中涵盖了异步加载框架核心原理,如下:

public abstract class MyAsycnTask {    private Handler handler = new Handler(){        public voID handleMessage(androID.os.Message msg) {            postTask();        };    };    /**     * 在子线程之前执行的 *** 作     */    public abstract voID preTask();    /**     * 在子线程之中执行的 *** 作     */    public abstract voID doinBack();    /**     * 在子线程之后执行的 *** 作     */    public abstract voID postTask();    /**     * 执行     */    public voID execute(){        preTask();        new Thread(){            public voID run() {                doinBack();                handler.sendEmptyMessage(0);            };        }.start();    }}

调用手写异步加载框架

new MyAsycnTask() {    @OverrIDe    public voID preTask() {        //在子线程之前执行的 *** 作    }    @OverrIDe    public voID postTask() {        //在子线程之中执行的 *** 作    }    @OverrIDe    public voID doinBack() {        //在子线程之后执行的 *** 作    }}.execute();

2)系统异步加载框架AsycnTask

系统异步加载框架AsycnTask三个参数:提高兼容性(如果某个泛型参数不需要指定类型,可将其指定为voID)
参数1:子线程执行所需的参数;参数2:显示当前的加载进度;参数3:子线程执行的结果;

接下来开始调用系统异步加载框架,用法如下:

new AsyncTask<String, Integer, String>(){    //在子线程之中执行的 *** 作    @OverrIDe    protected String doInBackground(String... params) {        // Todo auto-generated method stub        return null;    }    //在子线程之前执行的 *** 作    @OverrIDe    protected voID onPreExecute() {        // Todo auto-generated method stub        super.onPreExecute();    }    //在子线程之后执行的 *** 作    @OverrIDe    protected voID onPostExecute(String result) {        // Todo auto-generated method stub        super.onPostExecute(result);    }    //显示当前加载进度    @OverrIDe    protected voID onProgressUpdate(Integer... values) {        // Todo auto-generated method stub        super.onProgressUpdate(values);    }}.execute();

本篇是对AndroID界面编程的补充,而且都是高频常用的一些方法机制,建议重点学习。

总结

以上是内存溢出为你收集整理的Android 事件处理探险全部内容,希望文章能够帮你解决Android 事件处理探险所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1002382.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)