1114 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.

8voto

Hayi Nukman Punkte 1039

In Kotlin, setzen Context/App Context in Companion-Objekt noch produzieren Warnung Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)

oder wenn Sie etwas wie dieses verwenden:

    companion object {
        lateinit var instance: MyApp
    }

Es ist einfach täuschen die Lint nicht das Speicherleck zu entdecken, die App-Instanz kann immer noch Speicherleck produzieren, da Application-Klasse und seine Nachkommen ein Kontext ist.

Alternativ können Sie auch funktionale Schnittstellen oder funktionale Eigenschaften verwenden, um den Kontext Ihrer Anwendung zu erhalten.

Erstellen Sie einfach eine Objektklasse:

object CoreHelper {
    lateinit var contextGetter: () -> Context
}

oder Sie können es sicherer verwenden, indem Sie einen nullbaren Typ verwenden:

object CoreHelper {
    var contextGetter: (() -> Context)? = null
}

und fügen Sie in Ihrer App-Klasse diese Zeile hinzu:

class MyApp: Application() {

    override fun onCreate() {
        super.onCreate()
        CoreHelper.contextGetter = {
            this
        }
    }
}

und deklarieren Sie in Ihrem Manifest den Namen der Anwendung zu . MyApp

    <application
            android:name=".MyApp"

Wenn Sie den Kontext abfragen wollen, rufen Sie einfach auf:

CoreHelper.contextGetter()

// or if you use the nullable version
CoreHelper.contextGetter?.invoke()

Ich hoffe, es hilft.

8voto

Sheharyar Punkte 69702

Wenn Sie die Manifestdatei nicht ändern wollen, können Sie den Kontext manuell in einer statischen Variablen in Ihrer ersten Aktivität speichern:

public class App {
    private static Context context;

    public static void setContext(Context cntxt) {
        context = cntxt;
    }

    public static Context getContext() {
        return context;
    }
}

Und legen Sie einfach den Kontext fest, in dem Ihre Aktivität (oder Aktivitäten) beginnen:

// MainActivity

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Set Context
    App.setContext(getApplicationContext());

    // Other stuff
}

Nota: Wie bei allen anderen Antworten handelt es sich um ein potenzielles Speicherleck.

6voto

BlueWizard Punkte 352

Selon diese Quelle können Sie Ihren eigenen Kontext erhalten, indem Sie ContextWrapper erweitern

public class SomeClass extends ContextWrapper {

    public SomeClass(Context base) {
      super(base);
    }

    public void someMethod() {
        // notice how I can use "this" for Context
        // this works because this class has it's own Context just like an Activity or Service
        startActivity(this, SomeRealActivity.class);

        //would require context too
        File cacheDir = getCacheDir();
    }
}

JavaDoc für ContextWrapper

Proxying-Implementierung von Context, die einfach alle ihre Aufrufe an einen anderen Context delegiert. Kann unterklassifiziert werden, um das Verhalten zu ändern, ohne den ursprünglichen Context zu ändern.

5voto

barwnikk Punkte 920

Sie können die folgenden Möglichkeiten nutzen:

MainActivity.this.getApplicationContext();

MainActivity.java:

...
public class MainActivity ... {
    static MainActivity ma;
...
    public void onCreate(Bundle b) {
         super...
         ma=this;
         ...

Jede andere Klasse:

public ...
    public ANY_METHOD... {
         Context c = MainActivity.ma.getApplicationContext();

5voto

Versa Punkte 604

Wenn Sie aus irgendeinem Grund Anwendungskontext in einer beliebigen Klasse wünschen, nicht nur in solchen, die Anwendung/Aktivität erweitern, vielleicht für einige Fabrik- oder Hilfsklassen. Sie können das folgende Singleton zu Ihrer Anwendung hinzufügen.

public class GlobalAppContextSingleton {
    private static GlobalAppContextSingleton mInstance;
    private Context context;

    public static GlobalAppContextSingleton getInstance() {
        if (mInstance == null) mInstance = getSync();
        return mInstance;
    }

    private static synchronized GlobalAppContextSingleton getSync() {
        if (mInstance == null) mInstance = 
                new GlobalAppContextSingleton();
        return mInstance;
    }

    public void initialize(Context context) {
        this.context = context;
    }

    public Context getApplicationContext() {
        return context;
    }
}

und initialisieren Sie es dann im onCreate Ihrer Anwendungsklasse mit

GlobalAppContextSingleton.getInstance().initialize(this);

Sie können es überall verwenden, indem Sie

GlobalAppContextSingleton.getInstance().getApplicationContext()

Ich empfehle diesen Ansatz jedoch nur für den Anwendungskontext. Da es Speicherlecks verursachen kann.

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