[读书笔记]监听事件的四种方式原理分析(接口回调)与比较
来源:互联网 发布:影视后期网络培训学校 编辑:程序博客网 时间:2024/06/07 08:41
- 方式一:在布局文件的控件上设置onClick属性
布局文件:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="sayHello" android:text="HELLO"/></LinearLayout>
在源文件中绑定点击事件:
/** * ============================================================================= * Copyright (c) 2016 yuxin All rights reserved. * Packname work * Created by yuxin. * Created time 2016/9/21 0021 上午 8:38. * Version 1.0; * Describe : * History: * ============================================================================== */public class LoginOkActivity2 extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.dome); } public void doClick(View view) { //do something }}
这种方式代码简洁,结构清晰,唯一的缺点是android:onClick注册在debug时能运行正常,切换成release版本时release版本通常会混淆代码,方法的名称就改变了,所以这种方式虽然简单,但是不推荐。
在介绍后面几种方法前我们先提下java中方法的回调,下面这图是我对回调的理解:
如果还没看懂或则觉得我的理解有问题的,可以baidu看下别人的解释
- 方式二:匿名内部类作为事件监听器类
/** * ============================================================================= * Copyright (c) 2016 yuxin All rights reserved. * Packname com.jju.yuxin.disanzhou * Created by yuxin. * Created time 2016/9/21 0021 上午 10:50. * Version 1.0; * Describe : * History: * ============================================================================== */public class ClickDome extends Activity { private Button bt_click; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_click); bt_click = (Button) findViewById(R.id.bt_click); bt_click.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //do something } }); }}
很多监听事件只是临时的使用一次,或则有的一类监听操作只有一个控件执行,那么可以使用这种,也是使用比较广泛的一种监听方式,但是对于java来说,这种耦合有点紧,没有模块化的。
- 方式三:内部类作为监听器
public class ClickDome extends Activity { private Button bt_click; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_click); bt_click = (Button) findViewById(R.id.bt_click); MyClickListener listtener = new MyClickListener(): bt_click.setOnClickListener(listtener); } private class MyClickListener implements View.OnClickListener { @Override public void onClick(View v) { switch (v.getId()) { case R.id.bt_click: break; default: break; } } }}
当然也可以将内部类放置出来另写一个监听类,这种方式在java上符合单一职责原则,耦合度低,但是带来的确实更多的代码编写量,庆幸的是带来了可复用性,只要同一类监听操作我们都只传入一个监听类对象搞定,然后在switch中写上代码,但是记得的是,不同的activity千万别放在一个监听类里面操作,可能一时爽,痛苦起来会发疯。
- 方式四:Activity继承监听事件,Activity本身作为事件监听器
/** * ============================================================================= * Copyright (c) 2016 yuxin All rights reserved. * Packname com.jju.yuxin.disanzhou * Created by yuxin. * Created time 2016/9/21 0021 上午 10:50. * Version 1.0; * Describe : * History: * ============================================================================== */public class ClickDome extends Activity implements View.OnClickListener { private Button bt_click; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_click); bt_click = (Button) findViewById(R.id.bt_click); bt_click.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.bt_click: //do something break; default: break; } }}
这种方法其实和上面的方式三差不多,在这种方式里,监听类的对象都不用new了,因为就是本身,传入一个this就行了,但是你不觉得Activity一个界面类来实现监听接口有点不伦不类嘛?
综合上面四种方式,各有各的优势与劣势,在实际场景中灵活运用才是正道。
这博客就写完了嘛??不不不,,本博主和哪些妖艳贱货不一样,肯定要写点其他的东西啊,不然前面的方法回调不是白白铺垫了嘛,我们仔细的看下后面三种方式,其实原理都一样,都是为了实现onClick()这个方法,我们来看下setOnClickListener();这个方法,因为Buttom是View的子类,我们看下View里面的setOnClickListener()方法,
/** * Register a callback to be invoked when this view is clicked. If this view is not * clickable, it becomes clickable. * * @param l The callback that will run * * @see #setClickable(boolean) */ public void setOnClickListener(@Nullable OnClickListener l) { if (!isClickable()) { setClickable(true); } getListenerInfo().mOnClickListener = l; }
他就做了两件事情,一、把控件置为可点击的,二、将OnClickListener 对象赋值给getListenerInfo方法里面的mOnClickListener属性,我们看下这两个方法:
/** * Enables or disables click events for this view. When a view * is clickable it will change its state to "pressed" on every click. * Subclasses should set the view clickable to visually react to * user's clicks. * * @param clickable true to make the view clickable, false otherwise * * @see #isClickable() * @attr ref android.R.styleable#View_clickable */ public void setClickable(boolean clickable) { setFlags(clickable ? CLICKABLE : 0, CLICKABLE); }
他在这里立了个flag
ListenerInfo getListenerInfo() { if (mListenerInfo != null) { return mListenerInfo; } mListenerInfo = new ListenerInfo(); return mListenerInfo; }
这里也是非空判断下,返回个属性
这下我慌了,下一步它往哪里走呢??后来我看到了这个方法boolean performAccessibilityActionInternal(int action, Bundle arguments)
(名字有点长)
/** * @see #performAccessibilityAction(int, Bundle) * * Note: Called from the default {@link AccessibilityDelegate}. * * @hide */ public boolean performAccessibilityActionInternal(int action, Bundle arguments) { . . . . switch (action) { case AccessibilityNodeInfo.ACTION_CLICK: { if (isClickable()) { performClick(); return true; } } break; . . . return false; }
中间其他的我们都不关系,我们看下注释Note: Called from the default {@link AccessibilityDelegate}.大概意思就是说它会被另一个方法默认调用,我们看下switch
/** * Indicates whether this view reacts to click events or not. * * @return true if the view is clickable, false otherwise * * @see #setClickable(boolean) * @attr ref android.R.styleable#View_clickable */ @ViewDebug.ExportedProperty public boolean isClickable() { return (mViewFlags & CLICKABLE) == CLICKABLE; }
这个isClickable()就是返回之前setClickable()的值,我记得方法一进来就设置为了true,那我们看下performClick();
/** * Call this view's OnClickListener, if it is defined. Performs all normal * actions associated with clicking: reporting accessibility event, playing * a sound, etc. * * @return True there was an assigned OnClickListener that was called, false * otherwise is returned. */ public boolean performClick() { final boolean result; final ListenerInfo li = mListenerInfo; if (li != null && li.mOnClickListener != null) { playSoundEffect(SoundEffectConstants.CLICK); li.mOnClickListener.onClick(this); result = true; } else { result = false; } sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); return result; }
其他的都不重要。我们看到它通过各种传递和判断,将我们传进来的OnClickListener对象调用它的onClick()方法;。。而我们来看下onClick()
/** * Interface definition for a callback to be invoked when a view is clicked. */ public interface OnClickListener { /** * Called when a view has been clicked. * * @param v The view that was clicked. */ void onClick(View v); }
他是View类里面的OnClickListener接口的一个没有实现的方法,而这个方法就是我们在监听类里面实现的void onClick(View v)方法,结合之前的方法回调的图,这个应该知道工作模式了把!
关于绑定监听事件的原理应该是在LayoutInflater.from(this).inflate();实现,里面有对资源XML的解析生成View树图,但是原理我还没看,有兴趣的可以自己看下
我的博客网站http://huyuxin.top/欢迎大家访问!评论!
- [读书笔记]监听事件的四种方式原理分析(接口回调)与比较
- Android 四种绑定监听事件的方式
- Android监听事件添加动作的四种方式
- Android的四种监听事件处理方式
- Android四种绑定监听事件的方式
- Android 四种绑定监听事件的方式
- Android 四种绑定监听事件的方式
- jQuery中的四种事件监听方式
- 通过接口回调方式来设置RecyclerView的条目点击监听事件
- KAZE 算法原理与源码分析(四)KAZE特征的性能分析与比较
- 接口回调,以Android的事件监听为例
- Java解析XML的四种方式详解与比较
- Button的四种监听方式
- Android监听的四种方式
- button按钮的四种监听方式
- Android实现监听的四种方式
- android事件监听的两种方式
- 监听事件的几种实现方式
- fis系列-基于fis3前后端工程解决方案weg
- Android探索之旅 | Material Design学习资源
- okHttp日常使用笔记
- android 控件 swipe+recycler 分页基类
- LeetCode 4. Median of Two Sorted Arrays
- [读书笔记]监听事件的四种方式原理分析(接口回调)与比较
- Android沉浸状态栏的实现,支持4.4以上
- python自学笔记8之安装anaconda
- Mysql 会导致锁表的语法
- [绍棠] iOS post方式上传文件
- 谈谈对Spring IOC的理解
- Linux内核笔记(二) 系统调用
- 3.6
- 你会读书吗?