日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android 判断按钮是否已经有onclicklinstener,通过点击事件监听setOnClickListener彻底理解回调...

發布時間:2025/4/5 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 判断按钮是否已经有onclicklinstener,通过点击事件监听setOnClickListener彻底理解回调... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

老司機們對于回調肯定熟悉得不能再熟悉了,但是新司機可能還是一臉懵逼的,我比較笨,當年懵逼了好久,看夏安明的這一篇博客地址,雖然下邊的留言都是,寫得好!懂了懂了!但是我當時看了三遍還是不懂好嗎 - -,現在我站在我的角度,用我理解的方式給大家講解回調,我這么笨都理解了,聰明的新司機們肯定也是可以的

setOnClickListener分析

setOnCLickLinstener,只要寫過Android的同學應該都見過,大家都知道是點擊事件監聽,但是是怎么實現的呢?對,你沒有猜錯,就是回調

你在onClick(View view)中寫的方法,就是一個回調方法,你仔細想一想,這個方法是在你傳的參數new View.OnClickListener()中的方法,你再仔細的想一想,為什么你傳入了new View.OnClickListener()這個參數,Android Studio就會自動補全,讓你去實現onClick(View

view)這個方法呢?

一切都在你想象之中,OnClickListener就是一個接口,new出一個接口,你就得實現他里邊的抽象方法,在Android中,大多數回調都是靠接口來進行的

并且,你實現了onClick(View view)方法后,這個方法并沒有在我們的Activity或者Fragment中調用,那為什么他生效了呢?這就是回調,你實現了他,而他卻是在另一個地方調用的

那是在什么地方調用的呢?

我們點進setOnClickListener方法中一探虛實

于是我們跳到了View.java,原來這個方法是寫在View中的,這時你想到,第一行代碼中說了,我們的控件都繼承于View,原來如此 public void setOnClickListener(@Nullable OnClickListener l){

if (!isClickable()) {

setClickable(true);

}

getListenerInfo().mOnClickListener = l;

}

復制代碼

setOnClickListener方法就如同我們調用時的那樣,傳入一個OnClickListener對象作為參數,那我們來看一看OnClickListener是個啥子 public interface OnClickListener {

/**

* Called when a view has been clicked.

*

* @param v The view that was clicked.

*/

void onClick(View v);

}

復制代碼

果然不出你所料,就是個interface

然后注意這一行 getListenerInfo().mOnClickListener = l;

復制代碼

把我們傳入的OnClickListener對象賦值給了getListenerInfo().mOnClickListener,記住我們傳入的OnClickListener對象就相當于攜帶了我們實現的onClick(View view)方法,進到View里邊來了

記好了哦!

我們來看看getListenerInfo()方法 ListenerInfo getListenerInfo(){

if (mListenerInfo != null) {

return mListenerInfo;

}

mListenerInfo = new ListenerInfo();

return mListenerInfo;

}

復制代碼

getListenerInfo()返回一個ListenerInfo,如果mListenerInfo已經存在,就返回,如果不存在,就new一個返回,也許你已經知道,或許不久后你就知道,這叫單例模式,保證只有一個ListenerInfo對象

然后我們來看看ListenerInfo又是個啥子 static class ListenerInfo{

protected OnFocusChangeListener mOnFocusChangeListener;

private ArrayList mOnLayoutChangeListeners;

protected OnScrollChangeListener mOnScrollChangeListener;

private CopyOnWriteArrayList mOnAttachStateChangeListeners;

public OnClickListener mOnClickListener;

protected OnLongClickListener mOnLongClickListener;

protected OnContextClickListener mOnContextClickListener;

protected OnCreateContextMenuListener mOnCreateContextMenuListener;

private OnKeyListener mOnKeyListener;

private OnTouchListener mOnTouchListener;

private OnHoverListener mOnHoverListener;

private OnGenericMotionListener mOnGenericMotionListener;

private OnDragListener mOnDragListener;

private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;

OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;

}

復制代碼

原來是一個內部靜態類,成員包括各種事件的監聽接口,其中包括 public OnClickListener mOnClickListener;

復制代碼

誒喲,和我們傳入的一樣的一個OnClickListener接口引用,于是繞了這么一大圈(我們先不管為啥繞),我們傳入的持有我們實現的onClick(View view)方法的OnClickListener接口對象(還記得嗎?),被賦值到了View中的mListenerInfo中的mOnClickListener對象,也就是,我們實現的onCLick(View view) 方法,被mListenerInfo.mOnClickListener持有了

這時,你應該想到了,我們實現的onClick(View view)應該就是在 View中被調用了,bingo! 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;

}

復制代碼

從字面意思理解,這個方法就是執行Click的方法,

他將mListenerInfo對象傳給了一個靜態的ListenerInfo對象,

li,后邊的故事大家都知道了 li.mOnClickListener.onClick(this);

復制代碼

這個方法執行了點擊事件,并調用了我們實現的onClick(View view) 方法

讓我們來梳理一遍流程,我們在Activity或者Fragment中調用

View.setOnClickListener方法,傳入一個OnCLickListener對象,實現了onCLick(View view)方法,然后在View中的某個地方,我們實現的onCLick(View view)被調用,實現了回調,這就是回調的流程

異步

回調有什么用呢,就是異步,想象一下,系統一直在監聽著屏幕的點擊事件,在我們觸摸到屏幕的時候進行響應,這是一個線程操作,因為如果這個放在主線程,那在事件被響應之前,我們的線程都是阻塞的,因為屏幕的資源被占用了,無法進行其他操作,而在子線程中,系統監聽著屏幕的活動,然后在我們觸摸時,調用performClick()方法實現了點擊,并且調用了onClick(View view)方法實現了點擊事件的回調,我們就可以恰恰剛好在點擊時間觸發的時候,進行我們想要的操作,也就是我們實現的on

CLick(View view)方法

半偽代碼實現一個回調給你看

A.class //先定義一個接口

public interface Listener {

//回調方法

void 回調方法();

}

//申明一個接口

private Listener mLinstener;

//一個set接口的方法

public void setListener(Listener listener){

//把傳入的listener賦值給mLinstener

mLinstener = listener

}

...

//在某個地方,進行某個操作的時候

private void 某個操作() {

//回調方法執行

mLinstener.回調方法();

}

復制代碼

另一個類 B.class private A a = new A();

a.setListener(new Linstener() {

public void 回調方法() {

//我要在A中某個操作()執行的時候要搞的事情

搞事情阿搞事情();

}

});

復制代碼

然后在某個操作()調用的時候,我們的回調方法()也就被調用開始搞事情了

你如果看不懂的話,自己寫一遍,這就是Android中回調的一般寫法,你可以在各種自定義View中用來了,用著用著就理解了

為啥要繞那一圈

那一圈保證了View中只有一個mOnClickListener對象,保證了我們一次只執行一次onClick() 方法

最后

新司機們如果覺得有幫助,麻煩請給我的github項目點一個star

地址點這里

總結

以上是生活随笔為你收集整理的android 判断按钮是否已经有onclicklinstener,通过点击事件监听setOnClickListener彻底理解回调...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。