1097 Stimmen

Statischer Weg, um 'Context' in Android zu erhalten?

Gibt es eine Möglichkeit, die aktuelle Context Instanz innerhalb einer statischen Methode?

Ich bin auf der Suche nach dieser Möglichkeit, weil ich es hasse, die Instanz "Context" jedes Mal zu speichern, wenn sie sich ändert.

1411voto

Rohit Ghatol Punkte 14098

Tun Sie dies:

Geben Sie in der Android-Manifest-Datei Folgendes an.

<application android:name="com.xyz.MyApplication">

</application>

Dann schreiben Sie die Klasse:

public class MyApplication extends Application {

    private static Context context;

    public void onCreate() {
        super.onCreate();
        MyApplication.context = getApplicationContext();
    }

    public static Context getAppContext() {
        return MyApplication.context;
    }
}

Jetzt überall anrufen MyApplication.getAppContext() um Ihren Anwendungskontext statisch zu erhalten.

117voto

Jared Rummler Punkte 36806

Die meisten Anwendungen, die eine bequeme Methode zum Abrufen des Anwendungskontexts benötigen, erstellen ihre eigene Klasse, die die android.app.Application .

GUIDE

Sie können dies erreichen, indem Sie zunächst eine Klasse in Ihrem Projekt wie die folgende erstellen:

import android.app.Application;
import android.content.Context;

public class App extends Application {

    private static Application sApplication;

    public static Application getApplication() {
        return sApplication;
    }

    public static Context getContext() {
        return getApplication().getApplicationContext();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        sApplication = this;
    }
}

Dann sollten Sie in Ihrem AndroidManifest den Namen Ihrer Klasse im Tag AndroidManifest.xml angeben:

<application 
    ...
    android:name="com.example.App" >
    ...
</application>

Sie können dann den Anwendungskontext in jeder statischen Methode wie folgt abrufen:

public static void someMethod() {
    Context context = App.getContext();
}

WARNUNG

Bevor Sie so etwas in Ihr Projekt einbauen, sollten Sie sich überlegen, was in der Dokumentation steht:

Normalerweise ist es nicht notwendig, Application zu unterklassifizieren. In den meisten Situationen, können statische Singletons die gleiche Funktionalität auf modularere Weise Weise bereitstellen. Wenn Ihr Singleton einen globalen Kontext benötigt (z.B. zur Registrierung von Broadcast-Empfänger), kann die Funktion, die ihn abruft, mit einem Context übergeben werden, der intern Context.getApplicationContext() verwendet, wenn wenn das Singleton zum ersten Mal konstruiert wird.


REFLECTION

Es gibt auch eine andere Möglichkeit, den Anwendungskontext mit Hilfe von Reflection zu erhalten. Reflection wird in Android oft verachtet und ich persönlich denke, dass dies nicht in der Produktion verwendet werden sollte.

Um den Anwendungskontext abzurufen, müssen wir eine Methode für eine verborgene Klasse aufrufen ( ActivityThread ), die seit API 1 verfügbar ist:

public static Application getApplicationUsingReflection() throws Exception {
    return (Application) Class.forName("android.app.ActivityThread")
            .getMethod("currentApplication").invoke(null, (Object[]) null);
}

Es gibt eine weitere versteckte Klasse ( AppGlobals ), die eine Möglichkeit bietet, den Anwendungskontext auf statische Weise zu erhalten. Es erhält den Kontext mit ActivityThread Es gibt also keinen wirklichen Unterschied zwischen der folgenden Methode und der oben beschriebenen:

public static Application getApplicationUsingReflection() throws Exception {
    return (Application) Class.forName("android.app.AppGlobals")
            .getMethod("getInitialApplication").invoke(null, (Object[]) null);
} 

Viel Spaß beim Codieren!

67voto

Alessio Punkte 2864

Wenn wir davon ausgehen, dass es darum geht, den Anwendungskontext zu erhalten, habe ich es wie von @Rohit Ghatol vorgeschlagen implementiert, indem ich Application. Was dann passierte, war, dass es keine Garantie dafür gibt, dass der auf diese Weise abgerufene Kontext immer nicht null ist. Zu dem Zeitpunkt, an dem man ihn braucht, will man in der Regel einen Helfer initialisieren oder eine Ressource abrufen, die man nicht aufschieben kann; die Behandlung des Null-Falls hilft einem nicht. Ich habe also verstanden, dass ich im Grunde gegen die Android-Architektur kämpfe, wie in der docs

Hinweis: Normalerweise ist es nicht notwendig, Application zu unterklassifizieren. In den meisten Situationen können statische Singletons die gleiche Funktionalität auf modularere Weise bereitstellen. Wenn Ihr Singleton einen globalen Kontext benötigt (zum Beispiel um Broadcast-Empfänger zu registrieren), fügen Sie Context.getApplicationContext() als Context-Argument ein, wenn Sie die getInstance()-Methode Ihres Singletons aufrufen.

und erklärt von Dianne Hackborn

Der einzige Grund, warum es Application als etwas gibt, von dem man ableiten kann, ist, dass einer unserer Anwendungsentwickler mich während der Vor-1.0-Entwicklung ständig damit genervt hat, dass er ein Top-Level-Anwendungsobjekt braucht, von dem er ableiten kann, damit er ein für ihn "normaleres" Anwendungsmodell hat, und ich habe schließlich nachgegeben. Ich werde es immer bereuen, dass ich nachgegeben habe :)

Sie schlägt auch die Lösung für dieses Problem vor:

Wenn Sie einen globalen Zustand wünschen, der von verschiedenen Teilen Ihrer Anwendung gemeinsam genutzt werden kann, verwenden Sie ein Singleton. [...] Und das führt natürlich dazu, wie Sie diese Dinge verwalten sollten - sie bei Bedarf initialisieren.

Was ich also tat, war, die Erweiterung Application loszuwerden und den Kontext direkt an getInstance() des Singleton-Helpers zu übergeben, während ich einen Verweis auf den Anwendungskontext im privaten Konstruktor speicherte:

private static MyHelper instance;
private final Context mContext;    

private MyHelper(@NonNull Context context) {
    mContext = context.getApplicationContext();
}

public static MyHelper getInstance(@NonNull Context context) {
    synchronized(MyHelper.class) {
        if (instance == null) {
            instance = new MyHelper(context);
        }
        return instance;
    }
}

übergibt der Aufrufer dann einen lokalen Kontext an die Hilfskraft:

Helper.getInstance(myCtx).doSomething();

Um also die Frage richtig zu beantworten: Es gibt Möglichkeiten, statisch auf den Anwendungskontext zuzugreifen, aber von allen sollte abgeraten werden, und Sie sollten es vorziehen, einen lokalen Kontext an getInstance() des Singletons zu übergeben.


Interessierte können eine ausführlichere Version lesen unter fwd blog

51voto

Erich Douglass Punkte 51004

Nein, ich glaube nicht, dass es das gibt. Leider sind Sie darauf angewiesen, dass Sie getApplicationContext() von Activity oder eine der anderen Unterklassen von Context . Auch, este Frage ist in gewisser Weise verwandt.

40voto

phnmnn Punkte 11833

Kotlin Weg :

Manifest:

<application android:name="MyApplication">

</application>

MeineAnwendung.kt

class MyApplication: Application() {

    override fun onCreate() {
        super.onCreate()
        instance = this
    }

    companion object {
        lateinit var instance: MyApplication
            private set
    }
}

Sie können dann auf die Immobilie über MyApplication.instance

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X