Heim  >  Artikel  >  Backend-Entwicklung  >  Fallfreigabe zum Festlegen von Klickereignissen für die Ansicht im XML-Layout

Fallfreigabe zum Festlegen von Klickereignissen für die Ansicht im XML-Layout

黄舟
黄舟Original
2017-03-17 17:25:491485Durchsuche

Es ist üblich, ein Klicküberwachungs--Ereignis für eine Ansicht einzurichten, z. B.

    view.setOnClickListener(onClickListener);

. Eine andere Möglichkeit besteht darin, es direkt im XML-Layout Für die Rückrufmethode beim Klicken auf die Ansicht müssen Sie zunächst die Rückrufmethode in die Aktivität schreiben, z. B.

    public void onClickView(View view){
        // do something
    }
, und dann das Attribut

android:onClick der Ansicht festlegen in XML

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:onClick="onClickView" />
Manchmal ist es bequemer, Klickereignisse direkt aus dem XML-Layout festzulegen (insbesondere beim Schreiben von DEMO-Projekten). Sie können es grob erraten Die Verwendungsmethode „View“ sollte Reflektion verwenden, um die „onClickView“-Methode aus der Aktivität zu finden und sie aufzurufen, wenn sie ausgeführt wird, da dieser Ansatz keine Schnittstelle verwendet.

Als nächstes können wir analysieren, wie View die Callback-Methode aus dem Quellcode auslöst.

Fallfreigabe zum Festlegen von Klickereignissen für die Ansicht im XML-LayoutView verfügt über 5
Konstruktionsmethoden . Die erste wird intern verwendet. Die zweite Methode wird normalerweise verwendet, um View-Instanzen direkt zu erstellen Aus dem XML-Layout wird schließlich die fünfte Methode aufgerufen.

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;
                }
        }
}
Bestimmen Sie bei der Verarbeitung des onClick-Attributs zunächst, ob der Kontext der Ansicht eingeschränkt ist, und lösen Sie in diesem Fall eine IllegalStateException aus. Schauen Sie sich die isRestricted-Methode an.

    /**
     * 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 wird verwendet, um festzustellen, ob sich die aktuelle Context-Instanz in einem eingeschränkten Zustand befindet. Der offiziellen Erklärung zufolge ignoriert ein Context in einem eingeschränkten Zustand bestimmte Funktionen, z as Bestimmte Attribute von XML, offensichtlich das

-Attribut, das wir betrachten, werden ebenfalls ignoriert. android:onClick

Ein eingeschränkter Kontext kann bestimmte Funktionen deaktivieren. Beispielsweise würde eine mit einem eingeschränkten Kontext verknüpfte Ansicht bestimmte XML-Attribute ignorieren.

Die isRestricted-Methode ist jedoch eine davon die wenigen in Context Es gibt viele konkrete Implementierungsmethoden (der Rest sind im Grunde abstrakte Methoden), hier wird direkt false zurückgegeben, und diese Methode wird nur in ContextWrapper und MockContext


Fallfreigabe zum Festlegen von Klickereignissen für die Ansicht im XML-Layout

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 überschrieben Außerdem ruft der Agent nur isRestricted von mBase auf und MockContext wird nur beim Schreiben von

Unit-Tests verwendet, sodass isRestricted hier grundsätzlich nur false zurückgibt, es sei denn, ein benutzerdefinierter ContextWrapper wird verwendet und isRestricted wird neu geschrieben. Kehren Sie zur Ansicht zurück und
ruft dann tatsächlich die final String handlerName = a.getString(attr); Zeichenfolge android:onClick="onClickView" von „onClickView“ in ab und verwendet dann die Instanz der aktuellen Ansicht und „onClickView“, um eine DeclaredOnClickListener-Instanz zu erstellen. und als Klick-Listener der aktuellen Ansicht festlegen.

/**
     * 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);
        }
}
Hier ist klar, dass beim Klicken auf die Ansicht die Methode „onClick“ der DeclaredOnClickListener-Instanz aufgerufen wird und dann die Methode „resolveMethod“ aufgerufen wird, um sie mithilfe von Reflektion zu finden Der Kontext der Ansicht. Eine Methode heißt „onClickView“. Es ist zu beachten, dass die Methode „onClickView“ vom öffentlichen Typ sein muss, andernfalls wird beim Reflection-Aufruf eine IllegalAccessException ausgelöst.

Gleichzeitig ist aus dem Quellcode ersichtlich, dass die Methode zum Festlegen des Klickereignisses mit

darin besteht, die Rückrufmethode aus dem Kontext zu finden, also wenn Sie eine Ansicht im XML erstellen Für das Fragment können Sie diese Methode nicht verwenden, um die Rückrufmethode in Fragment zu binden, da Fragment selbst kein Kontext ist. Der Kontext der Ansicht ist hier tatsächlich FragmentActivity, was auch bedeutet, dass diese Methode schnell von Fragment zu FragmentActivity zurückrufen kann. android:onClick

Darüber hinaus ist die Funktion von

auch aus den Kommentaren der DeclaredOnClickListener-Klasse ersichtlich. android:onClick spielt hauptsächlich die Rolle des verzögerten Ladens . Nur wenn Sie auf „Ansicht“ klicken wird wissen, welche Methode für den Click-Callback verwendet wird.

Abschließend muss noch hinzugefügt werden, dass die Verwendung von

zum Festlegen eines Klickereignisses für View das Hinzufügen einer öffentlichen Methode ohne Schnittstelle zur Aktivität bedeutet. Der aktuelle Android-Entwicklungstrend lautet: „Schreiben Sie keine Geschäftslogik in die Aktivitätsklasse.“ Dies ist vorteilhaft für die Projektwartung und verhindert eine Aktivitätsexplosion. Versuchen Sie daher, in der Aktivität keine öffentlichen Methoden zu verwenden, die keine Schnittstelle und keinen Lebenszyklus betreffen. Daher kann die voreilige Verwendung von android:onClick die Aktivität „verunreinigen“. android:onClick


Das obige ist der detaillierte Inhalt vonFallfreigabe zum Festlegen von Klickereignissen für die Ansicht im XML-Layout. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn