Wie erhalte ich meinen Aktivitätskontext?

75

Ich habe nicht wirklich die Idee, wie das Ganze wirklich funktioniert. Wenn ich also eine Klasse habe A, die den Kontext einer Klasse benötigt, Bdie sich erweitert Activity, wie bekomme ich diesen Kontext?

Ich suche nach einem effizienteren Weg, als dem Klassenkonstruktor den Kontext als Parameter zu geben A. Wenn die Klasse beispielsweise AMillionen von Instanzen haben wird, haben wir am Ende Millionen redundanter Zeiger, Contextwährend wir in der Lage sein sollten, irgendwo nur eine und eine Getter-Funktion zu haben ...

Ofek Ron
quelle
4
classA.this ist Ihr Aktivitätskontext.
Padma Kumar
Aber warum brauchen Sie einen A-Kontext in Klasse B?
Rakesh
2
@ Rakesh Du verstehst es falsch ... er braucht den B-Kontext in Klasse A (was die Aktivität nicht erweitert). Das ist etwas Gemeinsames.
Cristian

Antworten:

43

Sie können die ApplicationKlasse (öffentliche Klasse im android.application-Paket) verwenden, dh:

Basisklasse für diejenigen, die den globalen Anwendungsstatus beibehalten müssen. Sie können Ihre eigene Implementierung bereitstellen, indem Sie den Namen im Tag Ihrer AndroidManifest.xml angeben. Dadurch wird diese Klasse für Sie instanziiert, wenn der Prozess für Ihre Anwendung / Ihr Paket erstellt wird.

Um diese Klasse zu verwenden, gehen Sie wie folgt vor:

public class App extends Application {

    private static Context mContext;

    public static Context getContext() {
        return mContext;
    }

    public static void setContext(Context mContext) {
        this.mContext = mContext;
    }

    ...

}

In Ihrem Manifest:

<application
        android:icon="..."
        android:label="..."
        android:name="com.example.yourmainpackagename.App" >
                       class that extends Application ^^^

In Aktivität B:

public class B extends Activity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sampleactivitylayout);

        App.setContext(this);
                  ...
        }
...
}

In Klasse A:

Context c = App.getContext();

Hinweis :

Es ist normalerweise nicht erforderlich, die Anwendung in eine Unterklasse zu unterteilen. In den meisten Situationen können statische Singletons dieselbe Funktionalität auf modularere Weise bereitstellen. Wenn Ihr Singleton einen globalen Kontext benötigt (zum Beispiel zum Registrieren von Rundfunkempfängern), kann der Funktion zum Abrufen ein Kontext zugewiesen werden, der beim erstmaligen Erstellen des Singletons intern Context.getApplicationContext () verwendet.

hasanghaforian
quelle
4
Kann ich fragen, warum OnInitListener implementiert werden muss?
Akari
Da Ihre App vermutlich eine Hauptaktivität hat (meine heißt MainActivity), können Sie alternativ die statischen ContextMitglieder in diese Klasse einordnen. (Nur weil Sie diese benutzerdefinierte Klasse bereits erstellt haben und daher keine weitere Klasse erstellen müssen, App.) Andererseits ist es wohl klarer, Dinge einzufügen App, die nicht wirklich damit zusammenhängen MainActivity.
ToolmakerSteve
1
In jedem Fall ist es wichtig, die Statik auf Null zu setzen, wenn Klasse B verschwindet. Andernfalls wird diese Klasse-B-Instanz, bei der es sich möglicherweise um eine Aktivität handelt, die viele Ressourcen enthält, erst nach dem Beenden Ihrer App einer GC unterzogen. (Wenn der Klasse B ist Ihre Haupttätigkeit, und Sie wollen es behalten herum , bis die App verlässt , dann diesen Kommentar ignorieren.)
ToolmakerSteve
3
Das statische Beibehalten von Kontexten kann in Android zu Speicherverlusten führen.
Marc Bacvanski
OnInitListenerdas ist in dekaliert TextToSpeech.OnInitListener?
János
53

Ok, ich werde ein kleines Beispiel geben, wie man das macht, was man verlangt

public class ClassB extends Activity
{

 ClassA A1 = new ClassA(this); // for activity context

 ClassA A2 = new ClassA(getApplicationContext());  // for application context. 

}
Gan
quelle
Danke vielmals! Es ist besser als eine ApplicationKlasse zu benutzen .
Acuna
34

Der beste und einfachste Weg, um den Aktivitätskontext zu erhalten, besteht darin, .thisnach dem Namen der Aktivität zu setzen. Beispiel: Wenn der Name Ihrer Aktivität lautet SecondActivity, lautet der KontextSecondActivity.this

John Alexander Betts
quelle
Ich frage mich, was der Unterschied zwischen dieser Lösung und der komplexeren akzeptierten Lösung ist - wenn es überhaupt einen Unterschied gibt.
David Gay
1
@ DavidGay getApplicationContext gibt den Kontext für die gesamte Anwendung zurück. Dies wird nicht empfohlen, zumindest müssen Sie den Anwendungskontext abrufen
John Alexander Betts
@ John Alexander Betts Danke! Dies sollte die akzeptierte Antwort sein und die höchste Stimme erhalten. Dies ist eine sehr einfache und direkte Antwort, die die Frage des OP tatsächlich beantwortet, im Gegensatz zu einer komplizierten, unklaren und fehleranfälligen hackartigen Lösung, die als Antwort akzeptiert wurde.
Pasignatur
3

Sie übergeben den Kontext an die Klasse B in ihrem Konstruktor und stellen sicher, dass Sie getApplicationContext () anstelle von activityContext () übergeben.

Hai
quelle
2
applicationContext und Aktivitätskontext sind unterschiedlich, sie haben unterschiedliche Lebensdauern und Sie sollten sie entsprechend verwenden.
Gan
@Gan hängt davon ab, wozu Klasse B überhaupt gut ist. Irgendwie gehe ich einfach davon aus, dass ApplicationContext nützlicher ist als der Aktivitätskontext. aber das bin nur ich :)
Shark
@Shark: Der Anwendungskontext ist nur ein Teilkontext und funktioniert für einige Dinge in bestimmten UI-bezogenen Vorgängen nicht.
Squonk
@ Quonk können Sie einige nennen? Ich habe keinen Fall festgestellt, in dem der Anwendungskontext fehlschlägt und der Aktivitätskontext nicht.
Hai
2
@Shark: Entschuldigung, ich habe das schlecht formuliert. Wenn die Anforderung nur eine Contextsein soll, funktioniert entweder der Anwendungskontext oder ein Aktivitätskontext. Wenn es sich bei der Klasse, an die der Kontext übergeben wird, jedoch um eine 'Helfer'-Klasse handelt, die möglicherweise UI-bezogene Arbeiten ausführt, wäre dies ctx.getWindowManager()beispielsweise kein gültiger Methodenaufruf, wenn ctxauf den Anwendungskontext verwiesen würde. Mit anderen Worten, es hängt wirklich davon ab, warum der Klasse ein "Kontext" übergeben werden muss und wofür sie benötigt wird.
Squonk
1

Sie können einen Konstruktor mit dem Parameter Kontext der Klasse A erstellen und dann diesen Kontext verwenden.

Kontext c;

A (Kontextkontext) {this.c = Kontext}

Aus der Aktivität B erstellen Sie mit diesem Konstruktor ein Objekt der Klasse A und übergeben getApplicationContext ().

Helal Khan
quelle
1

Wenn Sie den Kontext von A in B benötigen, müssen Sie ihn an B übergeben. Dazu können Sie die Aktivität A als Parameter übergeben, wie von anderen vorgeschlagen. Ich sehe nicht viel das Problem, dass die vielen Instanzen von A ihre eigenen Zeiger auf B haben, nicht sicher, ob das überhaupt so viel Aufwand bedeuten würde.

Aber wenn das das Problem ist, besteht eine Möglichkeit darin, den Zeiger auf A als eine Art globales, für die ApplicationKlasse verfügbares Element beizubehalten , wie @hasanghaforian vorgeschlagen hat. Abhängig davon, wofür Sie den Kontext benötigen, können Sie Applicationstattdessen sogar den Kontext des verwenden.

Ich würde vorschlagen, diesen Artikel über den Kontext zu lesen, um besser herauszufinden, welchen Kontext Sie benötigen.

Thomas
quelle
1
Da dies ein Jahr später ist als die akzeptierte Antwort, die bereits ausführlich zeigt, wie dies zu tun ist, sollte dies keine separate Antwort sein: Der einzige "neue" Teil ist der letzte Satz, der einen nützlichen Link enthält . Dies ist am besten als Kommentar zur akzeptierten Antwort.
ToolmakerSteve
1

In Kotlin wird sein:

activity?.applicationContext?.let {
         it//<- you context
        }
Serg Burlaka
quelle