ホームページ バックエンド開発 XML/RSS チュートリアル XML レイアウトでの表示のクリック イベントの設定に関するケースシェアリング

XML レイアウトでの表示のクリック イベントの設定に関するケースシェアリング

Mar 17, 2017 pm 05:25 PM

    view.setOnClickListener(onClickListener);
ログイン後にコピー
など、ビューのクリック監視 イベント

を設定するのが一般的です。もう 1 つの方法は、

XML レイアウトでビューがクリックされたときのコールバック メソッドを直接指定することです。 Activity メソッドにコールバック (

    public void onClickView(View view){
        // do something
    }
ログイン後にコピー

など) を記述し、View の android:onClick

android:onClick属性

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:onClick="onClickView" />
ログイン後にコピー

有的时候从XML布局里直接设定点击事件会比较方便(特别是在写DEMO项目的时候),这种做法平时用的人并不多,从使用方式上大致能猜出来,View应该是在运行的时候,使用反射的方式从Activity找到“onClickView”方法并调用,因为这种做法并没有用到任何接口。

接下来,我们可以从源码中分析出View是怎么触发回调方法的。

XML レイアウトでの表示のクリック イベントの設定に関するケースシェアリング
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中有重写
XML レイアウトでの表示のクリック イベントの設定に関するケースシェアリング

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&#39;t search up the hierarchy, null out and fail.
                    context = null;
                }
            }

            final int id = mHostView.getId();
            final String idText = id == NO_ID ? "" : " with id &#39;"
                    + mHostView.getContext().getResources().getResourceEntryName(id) + "&#39;";
            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:onClickrrreee

場合によっては、XML レイアウトから直接クリック イベントを設定する方が便利な場合があります (特にデモ プロジェクトを作成する場合)。通常、この方法を使用する人は多くありません。このアプローチではインターフェイスが使用されないため、ビューはリフレクションを使用してアクティビティから「onClickView」メソッドを見つけ、実行時にそれを呼び出す必要があります。


次に、View がソース コードからコールバック メソッドをトリガーする方法を分析できます。

🎜XML レイアウトでの表示のクリック イベントの設定に関するケースシェアリング🎜ビューには 5 つあります構築メソッド 🎜、最初のメソッドは内部で使用されます。通常、2 番目のメソッドは Java コード内で View インスタンスを直接作成するために使用され、XML レイアウトからレンダリングされた View インスタンスが作成されます。最終的には 5 番目のメソッドを呼び出します。 🎜rrreee🎜 onClick 属性を処理するときは、まずビューのコンテキストが制限されているかどうかを判断し、制限されている場合は IllegalStateException をスローします。 isRestricted メソッドを見てみましょう🎜rrreee🎜 isRestricted は、現在の Context インスタンスが制限された状態にあるかどうかを判断するために使用されます。公式の説明によると、制限された状態にある Context は XML の特定の属性などの特定の機能を無視します。明らかに、私たちが研究している android:onClick 属性も無視されます。 🎜
🎜制限されたコンテキストでは、特定の機能が無効になる場合があります。たとえば、制限されたコンテキストに関連付けられたビューは、特定の XML 属性を無視します。🎜
🎜ただし、isRestricted メソッドは、Context の数少ないメソッドの 1 つです。特定の実装 (残りは基本的に抽象メソッドです)、ここでは false を直接返します。このメソッドは ContextWrapper と MockContext でのみオーバーライドされます🎜XML レイアウトでの表示のクリック イベントの設定に関するケースシェアリング🎜rrreee🎜ContextWrapper はプロキシのみ mBase の isRestricted を呼び出しますが、MockContext は書き込まれます
これは単体テスト中にのみ使用されるため、カスタム ContextWrapper が使用され、isRestricted が書き換えられない限り、ここでの isRestricted は基本的に false のみを返します。 🎜ビューに戻り、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 サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

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

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

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

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

Golang を使用して強力なデスクトップ アプリケーションを開発する Golang を使用して強力なデスクトップ アプリケーションを開発する Mar 19, 2024 pm 05:45 PM

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

Lauiuiログインページでジャンプを設定する方法 Lauiuiログインページでジャンプを設定する方法 Apr 04, 2024 am 03:12 AM

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

vueで画像にタッチイベントを追加する方法 vueで画像にタッチイベントを追加する方法 May 02, 2024 pm 10:21 PM

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

Honmeng HarmonyOS と Go 言語の開発 Honmeng HarmonyOS と Go 言語の開発 Apr 08, 2024 pm 04:48 PM

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

同時プログラミングにおける C++ 関数のイベント駆動メカニズムとは何ですか? 同時プログラミングにおける C++ 関数のイベント駆動メカニズムとは何ですか? Apr 26, 2024 pm 02:15 PM

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

Webページ要素を取得するJavaScriptの詳細説明 Webページ要素を取得するJavaScriptの詳細説明 Apr 09, 2024 pm 12:45 PM

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

Python Tkinter で GUI の世界を征服する: 完全ガイド Python Tkinter で GUI の世界を征服する: 完全ガイド Mar 24, 2024 am 09:26 AM

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

jsのクリックイベントが繰り返し実行できない理由 jsのクリックイベントが繰り返し実行できない理由 May 07, 2024 pm 06:36 PM

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

See all articles