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。
所有基于回调的事件处理的回调方法返回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 事件处理探险所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)