XML レイアウトでの表示のクリック イベントの設定に関するケースシェアリング
view.setOnClickListener(onClickListener);
XML レイアウトでビューがクリックされたときのコールバック メソッドを直接指定することです。 Activity メソッドにコールバック (
public void onClickView(View view){ // do something }
android:onClick
android:onClick
属性
<View android:layout_width="match_parent" android:layout_height="match_parent" android:onClick="onClickView" />
有的时候从XML布局里直接设定点击事件会比较方便(特别是在写DEMO项目的时候),这种做法平时用的人并不多,从使用方式上大致能猜出来,View应该是在运行的时候,使用反射的方式从Activity找到“onClickView”方法并调用,因为这种做法并没有用到任何接口。
接下来,我们可以从源码中分析出View是怎么触发回调方法的。
View有5个构造方法,第一个是内部使用的,平时在Java代码中直接创建View实例用的是第二种方法,而从XML布局渲染出来的View实例最后都是要调用第五种方法。
public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { this(context); final TypedArray a = context.obtainStyledAttributes( attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes); for (int i = 0; i < N; i++) { int attr = a.getIndex(i); switch (attr) { …… // 处理onClick属性 case R.styleable.View_onClick: if (context.isRestricted()) { throw new IllegalStateException("The android:onClick attribute cannot " + "be used within a restricted context"); } final String handlerName = a.getString(attr); if (handlerName != null) { // 给当前View实例设置一个DeclaredOnClickListener监听器 setOnClickListener(new DeclaredOnClickListener(this, handlerName)); } break; } } }
处理onClick属性的时候,先判断View的Context是否isRestricted,如果是就抛出一个IllegalStateException异常。看看isRestricted方法
/** * Indicates whether this Context is restricted. * * @return {@code true} if this Context is restricted, {@code false} otherwise. * * @see #CONTEXT_RESTRICTED */ public boolean isRestricted() { return false; }
isRestricted是用于判断当前的Context实例是否出于被限制的状态,按照官方的解释,处限制状态的Context,会忽略某些特点的功能,比如XML的某些属性,很明显,我们在研究的android:onClick
属性也会被忽略。
a restricted context may disable specific features. For instance, a View associated with a restricted context would ignore particular XML attributes.
不过isRestricted方法是Context中为数不多的有具体实现的方法(其余基本是抽象方法),这里直接返回false,而且这个方法只有在ContextWrapper和MockContext中有重写
public class ContextWrapper extends Context { Context mBase; @Override public boolean isRestricted() { return mBase.isRestricted(); } } public class MockContext extends Context { @Override public boolean isRestricted() { throw new UnsupportedOperationException(); } }
ContextWrapper中也只是代理调用mBase的isRestricted,而MockContext是写单元测试的时候才会用到,所以这里的isRestricted基本只会返回false,除非使用了自定义的ContextWrapper并重写了isRestricted。
回到View,接着的final String handlerName = a.getString(attr);
其实就是拿到了android:onClick="onClickView"
中的“onClickView”这个字符串,接着使用了当前View的实例和“onClickView”创建了一个DeclaredOnClickListener实例,并设置为当前View的点击监听器。
/** * An implementation of OnClickListener that attempts to lazily load a * named click handling method from a parent or ancestor context. */ private static class DeclaredOnClickListener implements OnClickListener { private final View mHostView; private final String mMethodName; private Method mMethod; public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) { mHostView = hostView; mMethodName = methodName; } @Override public void onClick(@NonNull View v) { if (mMethod == null) { mMethod = resolveMethod(mHostView.getContext(), mMethodName); } try { mMethod.invoke(mHostView.getContext(), v); } catch (IllegalAccessException e) { throw new IllegalStateException( "Could not execute non-public method for android:onClick", e); } catch (InvocationTargetException e) { throw new IllegalStateException( "Could not execute method for android:onClick", e); } } @NonNull private Method resolveMethod(@Nullable Context context, @NonNull String name) { while (context != null) { try { if (!context.isRestricted()) { return context.getClass().getMethod(mMethodName, View.class); } } catch (NoSuchMethodException e) { // Failed to find method, keep searching up the hierarchy. } if (context instanceof ContextWrapper) { context = ((ContextWrapper) context).getBaseContext(); } else { // Can't search up the hierarchy, null out and fail. context = null; } } final int id = mHostView.getId(); final String idText = id == NO_ID ? "" : " with id '" + mHostView.getContext().getResources().getResourceEntryName(id) + "'"; throw new IllegalStateException("Could not find method " + mMethodName + "(View) in a parent or ancestor Context for android:onClick " + "attribute defined on view " + mHostView.getClass() + idText); } }
到这里就清楚了,当点击View的时候,DeclaredOnClickListener实例的“onClick”方法会被调用,接着会调用“resolveMethod”方法,使用反射的方式从View的Context中找一个叫“onClickView”方法,这个方法有一个View类型的参数,最后再使用反射调用该方法。要注意的是,“onClickView”方法必须是public类型的,不然反射调用时会抛出IllegalAccessException异常。
同时从源码也能看出,使用android:onClick
设置点击事件的方式是从Context里面查找回调方法的,所以如果对于在Fragment的XML里创建的View,是无法通过这种方式绑定Fragment中的回调方法的,因为Fragment自身并不是一个Context,这里的View的Context其实是FragmentActivity,这也意味着使用这种方式能够快速地从Fragment中回调到FragmentActivity。
此外,从DeclaredOnClickListener类的注释也能看出android:onClick
的功能,主要是起到懒加载的作用,只有到点击View的时候,才会知道哪个方法是用于点击回调的。
最后,特别需要补充说明的是,使用android:onClick
给View设置点击事件,就意味着要在Activity里添加一个非接口的public方法。现在Android的开发趋势是“不要把业务逻辑写在Activity类里面”,这样做有利于项目的维护,防止Activity爆炸,所以尽量不要在Activity里出现非接口、非生命周期的public方法。因此,贸然使用android:onClick
rrreee
次に、View がソース コードからコールバック メソッドをトリガーする方法を分析できます。

android:onClick
属性も無視されます。 🎜🎜制限されたコンテキストでは、特定の機能が無効になる場合があります。たとえば、制限されたコンテキストに関連付けられたビューは、特定の XML 属性を無視します。🎜🎜ただし、isRestricted メソッドは、Context の数少ないメソッドの 1 つです。特定の実装 (残りは基本的に抽象メソッドです)、ここでは false を直接返します。このメソッドは ContextWrapper と MockContext でのみオーバーライドされます🎜

final String handlerName = a.getString(attr);
は実際に android:onClick="onClickView"
文字列 🎜 を取得し、現在のビューのインスタンスと「onClickView」を使用して DeclaredOnClickListener インスタンスを作成し、クリック リスナーに設定します。現在のビューの場合。 🎜rrreee🎜ここで明らかです。ビューがクリックされると、DeclaredOnClickListener インスタンスの「onClick」メソッドが呼び出され、次にリフレクションを使用してビューの「onClickView」というメソッドが検索されます。 Context. 、このメソッドには View 型のパラメータがあり、最後にメソッドはリフレクションを使用して呼び出されます。 「onClickView」メソッドはパブリック型でなければならないことに注意してください。そうでない場合、リフレクション呼び出しが行われたときに IllegalAccessException がスローされます。 🎜🎜同時に、android:onClick
を使用してクリック イベントを設定する方法は、Context からコールバック メソッドを見つけることであることもソース コードからわかります。 Fragment 自体は Context ではないため、このメソッドは Fragment のコールバック メソッドをバインドします。これは、このメソッドが Fragment から FragmentActivity にすばやくコールバックできることも意味します。 。 🎜🎜さらに、DeclaredOnClickListener クラスのコメントから、 android:onClick
の機能も確認できます。これは主に View の場合のみ遅延読み込みとして機能するものです。クリックされると、クリック コールバックにどのメソッドが使用されるかがわかります。 🎜🎜最後に、追加する必要があるのは、android:onClick
を使用して View のクリック イベントを設定するということは、非インターフェイスのパブリック メソッドをアクティビティに追加することを意味するということです。現在の Android 開発トレンドは、「Activity クラスにビジネス ロジックを記述しない」です。これはプロジェクトの保守に有益であり、Activity の爆発を防ぐため、Activity には非インターフェイスおよび非ライフサイクルのパブリック メソッドを含めないようにしてください。したがって、 android:onClick
をむやみに使用すると、アクティビティが「汚染」される可能性があります。 🎜🎜🎜🎜以上がXML レイアウトでの表示のクリック イベントの設定に関するケースシェアリングの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









Golang を使用して強力なデスクトップ アプリケーションを開発する インターネットの継続的な発展に伴い、人々はさまざまな種類のデスクトップ アプリケーションから切り離すことができなくなりました。開発者にとって、強力なデスクトップ アプリケーションを開発するには効率的なプログラミング言語を使用することが重要です。この記事では、Golang (Go 言語) を使用して強力なデスクトップ アプリケーションを開発する方法を紹介し、いくつかの具体的なコード例を示します。 Golang は Google が開発したオープンソースのプログラミング言語で、シンプルさ、効率性、強力な同時実行性などの特徴があり、以下の用途に非常に適しています。

Layui ログインページジャンプ設定手順: ジャンプコードの追加: ログインフォーム送信ボタンクリックイベントに判定を追加し、ログイン成功後、window.location.href 経由で指定ページにジャンプします。フォーム構成を変更します。lay-filter="login" のフォーム要素に非表示の入力フィールドを追加します。名前は「redirect」、値はターゲット ページ アドレスです。

Vueで画像にクリックイベントを追加するにはどうすればよいですか? Vue インスタンスをインポートします。 Vue インスタンスを作成します。 HTML テンプレートに画像を追加します。 v-on:click ディレクティブを使用してクリック イベントを追加します。 Vue インスタンスで handleClick メソッドを定義します。

HarmonyOS と Go 言語開発の概要 HarmonyOS は Huawei が開発した分散オペレーティング システムであり、Go は最新のプログラミング言語であり、この 2 つの組み合わせにより、分散アプリケーション開発のための強力なソリューションが提供されます。この記事ではHarmonyOSでの開発におけるGo言語の使い方を紹介し、実践事例を通して理解を深めていきます。インストールとセットアップ Go 言語を使用して HarmonyOS アプリケーションを開発するには、まず GoSDK と HarmonyOSSDK をインストールする必要があります。具体的な手順は次のとおりです。 #GoSDK のインストールgogetgithub.com/golang/go#Set PATH

並行プログラミングのイベント駆動メカニズムは、イベントの発生時にコールバック関数を実行することによって外部イベントに応答します。 C++ では、イベント駆動メカニズムは関数ポインターを使用して実装できます。関数ポインターは、イベントの発生時に実行されるコールバック関数を登録できます。ラムダ式ではイベント コールバックを実装することもでき、匿名関数オブジェクトの作成が可能になります。実際のケースでは、関数ポインタを使用して GUI ボタンのクリック イベントを実装し、イベントの発生時にコールバック関数を呼び出してメッセージを出力します。

回答: JavaScript には、ID、タグ名、クラス名、CSS セレクターの使用など、Web ページ要素を取得するためのさまざまな方法が用意されています。詳細説明: getElementById(id): 一意の ID に基づいて要素を取得します。 getElementsByTagName(tag): 指定されたタグ名の要素グループを取得します。 getElementsByClassName(class): 指定されたクラス名の要素グループを取得します。 querySelector(selector): CSS セレクターを使用して、最初に一致した要素を取得します。 querySelectorAll(selector): CSS セレクターを使用して一致するものをすべて取得します

Tkinter は、クロスプラットフォームのグラフィカル ユーザー インターフェイス (GUI) を作成するための、Python 標準ライブラリの強力な GUI ツールキットです。これは Tcl/Tk ツールキットに基づいており、シンプルで直感的な構文を提供するため、Python 開発者は複雑なユーザー インターフェイスを簡単かつ迅速に作成できます。 Tkinter の利点 クロスプラットフォーム互換性: Tkinter アプリケーションは、Windows、Mac、Linux などのすべての主要なオペレーティング システムで実行されます。使いやすさ: 構文が明確で学びやすいため、初心者でも経験豊富な開発者でも簡単に習得できます。拡張性: Tkinter はさまざまなウィジェットとコントロールを提供し、開発者がさまざまなユーザー インターフェイスを作成できるようにします。統合: P に関連します。

JavaScript のクリック イベントは、イベント バブリング メカニズムのため、繰り返し実行できません。この問題を解決するには、次の措置を講じることができます。 イベント キャプチャを使用する: イベントがバブルアップする前に起動するイベント リスナーを指定します。イベントの引き継ぎ: イベントのバブリングを停止するには、event.stopPropagation() を使用します。タイマーを使用します。しばらくしてからイベント リスナーを再度トリガーします。
