Was ist der Unterschied zwischen den verschiedenen Methoden, um einen Kontext zu bekommen?

StackOverflow https://stackoverflow.com/questions/1026973

  •  06-07-2019
  •  | 
  •  

Frage

In verschiedenen Bits von Android Code, den ich gesehen habe:

 public class MyActivity extends Activity {
    public void method() {
       mContext = this;    // since Activity extends Context
       mContext = getApplicationContext();
       mContext = getBaseContext();
    }
 }

Allerdings kann ich keine anständige Erklärung davon finden bevorzugt, und unter welchen Umständen, die verwendet werden sollen.

Pointers auf die Dokumentation zu diesem Thema, und Führung über das, was brechen könnte, wenn die falsche gewählt wird, würde sehr geschätzt werden.

War es hilfreich?

Lösung

Ich bin damit einverstanden, dass Dokumentation spärlich ist, wenn es um Contexts in Android kommt, aber Sie können zusammen ein paar Fakten aus verschiedenen Quellen piece.

Dieser Blog-Eintrag auf der offiziell Google Android Entwickler-Blog geschrieben wurde meist Adresse Speicherlecks zu helfen, aber einige gute Informationen über Kontexte und sieht vor:

  

In einer normalen Android-Anwendung, Sie   hat in der Regel zwei Arten von Kontext,   Aktivität und Anwendung.

Lesen Sie den Artikel ein wenig weiter über den Unterschied zwischen den beiden erzählt, und wenn Sie als mit der Aktivität Kontext Activity.getApplicationContext() mit dem Anwendungskontext (this) eher vielleicht prüfen). Grundsätzlich ist der Anwendungskontext mit der Anwendung verknüpft und wird immer das gleiche sein während des gesamten Lebenszyklus Ihrer App, wo die Aktivität Zusammenhang mit der Tätigkeit verbunden ist, und möglicherweise viele Male zerstört werden könnte, wie die Aktivität während der Bildschirmausrichtung ändert zerstört und so.

Ich konnte nicht wirklich etwas finden, wenn getBaseContext () andere als ein Beitrag von Dianne Hackborn, einer der Google-Ingenieure arbeiten auf dem Android SDK zu verwenden:

  

Verwenden Sie kein getBaseContext (), nur verwenden   Context Sie haben.

Das war von einem Beitrag auf dem Android-Entwickler-Newsgroup , können Sie Ihre Frage auch dort zu prüfen, zu fragen, weil eine Handvoll Menschen auf Android tatsächlichen Monitor, die Newsgroup arbeitet und Fragen beantworten.

Insgesamt also scheint es vorzuziehen, den globalen Anwendungskontext, wenn möglich zu verwenden.

Andere Tipps

Hier ist, was ich in Bezug auf die Verwendung von context gefunden:

1). Innerhalb eines Activity selbst verwendet this für Layouts und Menüs aufbläst, Kontextmenüs registrieren, Widgets instanziiert wird, andere Aktivitäten starten, neue Intent innerhalb eines Activity, Vorlieben Instanziieren oder andere Methoden in einem Activity.

aufpumpen Layout:

View mView = this.getLayoutInflater().inflate(R.layout.myLayout, myViewGroup);

aufpumpen Menü:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    this.getMenuInflater().inflate(R.menu.mymenu, menu);
    return true;
}

Registrieren Kontextmenü:

this.registerForContextMenu(myView);

Instantiate widget:

TextView myTextView = (TextView) this.findViewById(R.id.myTextView);

Starten Sie eine Activity:

Intent mIntent = new Intent(this, MyActivity.class);
this.startActivity(mIntent);

Instantiate Vorlieben:

SharedPreferences mSharedPreferences = this.getPreferenceManager().getSharedPreferences();

2). Für anwendungsweite Klasse Verwendung getApplicationContext() als diesen Zusammenhang gibt es für die Lebensdauer der Anwendung.

Rufen Sie den Namen des aktuellen Android-Paket:

public class MyApplication extends Application {    
    public static String getPackageName() {
        String packageName = null;
        try {
            PackageInfo mPackageInfo = getApplicationContext().getPackageManager().getPackageInfo(getApplicationContext().getPackageName(), 0);
            packageName = mPackageInfo.packageName;
        } catch (NameNotFoundException e) {
            // Log error here.
        }
        return packageName;
    }
}

Binden eine anwendungsweiten Klasse:

Intent mIntent = new Intent(this, MyPersistent.class);
MyServiceConnection mServiceConnection = new MyServiceConnection();
if (mServiceConnection != null) {
    getApplicationContext().bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
.

3) für Hörer und eine andere Art von Android-Klassen (z ContentObserver), verwenden Sie eine Context Substitution wie:

mContext = this;    // Example 1
mContext = context; // Example 2

Dabei gilt this oder context ist der Kontext einer Klasse (Aktivität, etc.).

Activity Kontext Substitution:

public class MyActivity extends Activity {
    private Context mContext;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);        
        mContext = this;
    }
}

Listener Kontext Substitution:

public class MyLocationListener implements LocationListener {
    private Context mContext;
    public MyLocationListener(Context context) {
        mContext = context;
    }
}

ContentObserver Kontext Substitution:

public class MyContentObserver extends ContentObserver {
    private Context mContext;
    public MyContentObserver(Handler handler, Context context) {
        super(handler);
        mContext = context;
    }
}

4). Für BroadcastReceiver (einschließlich inlined / Embedded-Empfänger), verwenden Sie den eigenen Kontext des Empfängers.

Externe BroadcastReceiver:

public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        if (action.equals(Intent.ACTION_SCREEN_OFF)) {
            sendReceiverAction(context, true);
        }
        private static void sendReceiverAction(Context context, boolean state) {
            Intent mIntent = new Intent(context.getClass().getName() + "." + context.getString(R.string.receiver_action));
            mIntent.putExtra("extra", state);
            context.sendBroadcast(mIntent, null);
        }
    }
}

Inlined / Embedded BroadcastReceiver:

public class MyActivity extends Activity {
    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final boolean connected = intent.getBooleanExtra(context.getString(R.string.connected), false);
            if (connected) {
                // Do something.
            }
        }
    };
}

5). Für Dienstleistungen, verwenden Sie den eigenen Kontext des Service.

public class MyService extends Service {
    private BroadcastReceiver mBroadcastReceiver;
    @Override
    public void onCreate() {
        super.onCreate();
        registerReceiver();
    }
    private void registerReceiver() {
        IntentFilter mIntentFilter = new IntentFilter();
        mIntentFilter.addAction(Intent.ACTION_SCREEN_OFF);
        this.mBroadcastReceiver = new MyBroadcastReceiver();
        this.registerReceiver(this.mBroadcastReceiver, mIntentFilter);
    } 
}

6). Für Toasts, in der Regel getApplicationContext() verwenden, aber wenn möglich, verwenden Sie den Zusammenhang von einer Aktivität übergeben, Dienstleistung, etc.

Verwenden Kontext der Anwendung:

Toast mToast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG);
mToast.show();

Verwenden Kontext von einer Quelle übergeben:

public static void showLongToast(Context context, String message) {
    if (context != null && message != null) {
        Toast mToast = Toast.makeText(context, message, Toast.LENGTH_LONG);
        mToast.show();
    }
}

Und schließlich, nicht getBaseContext() verwenden, wie von Android Framework-Entwicklern beraten.

UPDATE:. Fügen Sie Beispiele für Context Verwendung

Ich lese diesen Thread vor ein paar Tagen, mir die gleiche Frage. Meine Entscheidung, nach der Lektüre dieses war einfach: immer verwenden application

.

Allerdings habe ich ein Problem damit begegnet, verbrachte ich ein paar Stunden, um es zu finden, und ein paar Sekunden, um es zu lösen ... (Wechsel ein Wort ...)

Ich bin ein LayoutInflater mit einer Ansicht zum Aufblasen eines Spinner enthält.

Hier sind also zwei Möglichkeiten:

1)

    LayoutInflater layoutInflater = LayoutInflater.from(this.getApplicationContext());

2)

    LayoutInflater layoutInflater = LayoutInflater.from(this.getBaseContext());

Dann mache ich etwas wie folgt aus:

    // managing views part
    View view = ContactViewer.mLayoutInflater.inflate(R.layout.aViewContainingASpinner, theParentView, false);
    Spinner spinner = (Spinner) view.findViewById(R.id.theSpinnerId);
    String[] myStringArray = new String[] {"sweet","love"};

    // managing adapter part
    // The context used here don't have any importance -- both work.
    ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this.getApplicationContext(), myStringArray, android.R.layout.simple_spinner_item);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter);

    theParentView.addView(view);

Was ich bemerkte: Wenn Sie Ihr Linearlayout mit dem application instanziiert, dann, wenn Sie auf dem Spinner in Ihrer Aktivität klicken, erhalten Sie eine abgefangene Ausnahme haben, von der virtuellen Maschine Dalvik (nicht aus dem Code kommen, das ist, warum ich habe eine Menge Zeit damit verbracht, um herauszufinden, wo mein Fehler war ...).

Wenn Sie die baseContext verwenden, dann ist das in Ordnung, wird das Kontextmenü öffnen, und Sie werden unter Ihren Möglichkeiten wählen können.

So, hier ist mein Fazit: Ich nehme an (ich habe es nicht getestet weiter) als die baseContext erforderlich, wenn mit contextMenu in Ihrer Aktivität zu tun ...

Der Test durchgeführt wurde mit API 8-Codierung, und auf einem HTC Desire getestet, Android 2.3.3.

Ich hoffe, dass mein Kommentar haben Sie nicht so weit gebohrt, und wünschen Ihnen alles Gute. Glückliche Codierung; -)

Zuerst habe ich damit einverstanden, dass wir appcontext wann immer möglich verwenden sollten. dann "this" in Tätigkeit. Ich habe noch nie ein Bedürfnis nach basecontext hatte.

In meinen Tests in den meisten Fällen können sie ausgetauscht werden. In den meisten Fällen wollen der Grund, Sie halten einen Kontext zu erhalten ist, den Zugriff auf Dateien, Einstellungen, Datenbank usw. reflektiert Diese Daten schließlich als Dateien in Ihrer App privaten Daten-Ordner (/ data / data /). Egal, welche Kontext Sie verwenden, werden sie in den gleichen Ordner zugeordnet werden / Dateien, so dass Sie in Ordnung sind.

Das ist, was ich beobachtet. Vielleicht gibt es Fälle, Sie sollten sie unterscheiden zu können.

In einigen Fällen können Sie Aktivität Kontext über Anwendungskontext verwenden, wenn etwas in einem Thread ausgeführt wird. Wenn Thread-Ausführung abgeschlossen ist, und Sie müssen das Ergebnis zurück an den Aufrufer Aktivität zurückzukehren, müssen Sie diesen Rahmen mit einem Handler.

((YourActivity) context).yourCallbackMethod(yourResultFromThread, ...);

In einfachen Worten

getApplicationContext() wie der Name Methode vorschlägt, wird Ihre App bewusst Anwendung breit Details machen, die Sie von überall in der App zugreifen können. So Sie nutzen diese in Service nutzen verbindlich, Broadcast-Anmeldung usw. Application context wird, bis die App verlässt noch am Leben sein.

getActivity() oder this Ihre App bewusst den aktuellen Bildschirm, der auch über die App-Ebene Details von application context bereitgestellt sichtbar ist. So wollen alles, was Sie über den aktuellen Bildschirm wie Window ActionBar Fragementmanger kennen und so sind mit diesem Zusammenhang zur Verfügung. Grundsätzlich und Activity Context erstrecken. Dieser Kontext wird lebendig, bis die aktuelle Komponente (Aktivität) lebt

Ich habe nur dieses und getBaseContext, wenn sie von einem onClick (sehr grün noob Java und Android) rösten. Ich benutze dies als meine Klicker direkt in der Tätigkeit und habe getBaseContext in einem anonymen inneren Klicker zu verwenden. Ich vermute, dass ist so ziemlich der Trick mit getBaseContext, es vielleicht zurückkehrt, den Kontext der Tätigkeit, bei der die innere Klasse versteckt.

  

Die Verwirrung rührt von der Tatsache, dass es zahlreiche Möglichkeiten,   Context-Zugang, mit (an der Oberfläche) ohne erkennbare Unterschiede.   Hier sind vier der häufigsten Arten zugreifen können Sie in der Lage sein,   Kontext in einer Aktivität.

getContext()
getBaseContext()
getApplicationContext()
getActionBar().getThemedContext() //new

Was ist ein Context? Ich mag persönlich von Kontext als der Zustand Ihrer Anwendung zu einem bestimmten Zeitpunkt zu denken. Der Anwendungskontext stellt eine globale oder Basiskonfiguration Ihrer Anwendung und eine Aktivität oder Service kann darauf aufbauen und stellt eine Konfiguration Instanz Ihrer Anwendung oder einen transitiven Zustand für sie.

Wenn Sie an der Quelle für android.content.Context betrachten, sehen Sie, dass Context ist eine abstrakte Klasse und die Kommentare zu der Klasse sind wie folgt:

Schnittstelle zu globalen Informationen über eine Anwendungsumgebung. Dies ist eine abstrakte Klasse, deren Umsetzung durch das Android-System zur Verfügung gestellt. Es ermöglicht den Zugriff auf application-specific Ressourcen und Klassen sowie up-Anrufe für application-level Operationen wie Start-Aktivitäten, den digitalen Rundfunk und Empfangen von Absichten usw. Was ich nehme weg von diesem ist, dass Kontext eine gemeinsame Implementierung für den Zugriff auf Anwendungsebene Ressourcen sowie auf Systemebene zur Verfügung stellt. Anwendungsebene Ressourcen werden Dinge wie String-Ressourcen [getResources()] oder Vermögenswerte [getAssets()] und System-Level-Ressource ist der Zugriff auf alles, was Sie mit Context.getSystemService(). zugreifen

Wie der Tat, werfen Sie einen Blick auf die Erläuterungen zu den Methoden, und sie scheinen diesen Begriff zu verstärken:

getSystemService(): Bringen Sie das Handle zu einem system-level Dienst mit Namen. Die Klasse des zurückgegebenen Objekts variiert je nach dem gewünschten Namen. getResources(): Gibt eine Ressource-Instanz für Ihre Anwendung Paket. getAssets(): Gibt eine Ressource-Instanz für Ihre Anwendung Paket. Es kann darauf hinzuweisen, dass im Kontext abstrakte Klasse, die alle der oben genannten Methoden abstrakt sind! Nur eine Instanz von getSystemService (Klasse) hat eine Implementierung und das ruft eine abstrakte Methode. Das heißt, sollte die Implementierung für diese von den implementierenden Klassen zur Verfügung gestellt meist werden, die Folgendes umfassen:

ContextWrapper
Application
Activity
Service
IntentService

Mit Blick auf die API-Dokumentation, die Hierarchie der Klassen sieht wie folgt aus:

Kontext

| - ContextWrapper

| - - Anwendung

| - - ContextThemeWrapper

| - - - - Aktivität

| - - Service

| - - - IntentService

Da wir diese Context wissen selbst keine Einsicht bereitstellt, bewegen wir den Baum nach unten und einen Blick auf die ContextWrapper nehmen und erkennen, dass es entweder nicht viel gibt. Da Anwendung ContextWrapper erstreckt, gibt es nicht viel dort zu betrachten, entweder weil sie nicht die Umsetzung von ContextWrapper bereitgestellt enthebt. Dies bedeutet, dass die Umsetzung für Kontext wird durch das OS zur Verfügung gestellt und wird von der API versteckt. Sie können für Context bei der konkreten Umsetzung einen Blick darauf werfen, indem man die Quelle für die ContextImpl Klasse suchen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top