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界面编程的补充,而且都是高频常用的一些方法机制,建议重点学习。

更多相关文章

  1. Android采用操作xml
  2. Android Studio按钮响应事件(一)
  3. Android 中如何关闭线程
  4. Android:Handler事件处理机制
  5. 巨人的崛起 Android操作系统发展历程
  6. android 玩转ContentProvider之二--实现多个ContentProvider对多张
  7. android ListView Item和CheckBox、Button点击事件冲突的问题
  8. android SQLite数据库的基本操作

随机推荐

  1. HTC Kaiser 编译Android Kernel zImage
  2. android中ProgressDialog与ProgressBar的
  3. Android 换肤
  4. Scala&Android下的开发trait经验分享
  5. unity安卓多个sdk合并
  6. Android(安卓)4.2 BT系统之蓝牙关闭过程
  7. 《第一行代码Android》阅读笔记
  8. 安卓学习(初)第三章(2)(《第一行代码》)
  9. Android应用程序中Manifest.java文件的介
  10. ap6234移植