¿Cuál es la diferencia entre los diversos métodos para obtener un contexto?

En varios bits del código de Android que he visto:

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

Sin embargo, no puedo encontrar ninguna explicación decente de cuál es preferible y bajo qué circunstancias debería usarse.

Se agradecerá mucho la documentación sobre esto y la orientación sobre lo que podría romperse si se elige el que no corresponde.

Estoy de acuerdo en que la documentación es escasa cuando se trata de Contextos en Android, pero puede reconstruir algunos hechos de diversas fonts.

Esta publicación de blog en el blog oficial de desarrolladores de Android de Google fue escrita principalmente para ayudar a solucionar memory leaks, pero también proporciona buena información sobre contextos:

En una aplicación regular de Android, generalmente tiene dos tipos de contexto, actividad y aplicación.

Leer el artículo un poco más acerca de la diferencia entre los dos y cuándo es posible que desee considerar el uso de la aplicación Contexto ( Activity.getApplicationContext() ) en lugar de utilizar el contexto de la actividad de this . Básicamente, el contexto de la aplicación está asociado con la aplicación y siempre será el mismo durante todo el ciclo de vida de la aplicación, ya que el contexto de la actividad se asocia con la actividad y posiblemente se destruirá muchas veces a medida que la actividad se destruya durante los cambios de orientación de la pantalla. tal.

No pude encontrar nada sobre cuándo usar getBaseContext () que no sea una publicación de Dianne Hackborn, uno de los ingenieros de Google que trabajan en el SDK de Android:

No use getBaseContext (), simplemente use el Contexto que tenga.

Eso fue de una publicación en el grupo de noticias android-developers , es posible que desee considerar hacer su pregunta allí también, porque un puñado de las personas que trabajan en Android monitorean ese grupo de noticias y responden preguntas.

Entonces, en general, parece preferible utilizar el contexto de aplicación global cuando sea posible.

Esto es lo que he encontrado con respecto al uso del context :

1). Dentro de una Activity sí, utilícela para inflar diseños y menús, registrar menús contextuales, crear instancias de widgets, iniciar otras actividades, crear nuevas Intent dentro de una Activity , crear instancias de preferencias u otros métodos disponibles en una Activity .

Inflar el diseño:

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

Menú inflar:

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

Menú de contexto de registro:

 this.registerForContextMenu(myView); 

Instalar el widget

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

Comience una Activity :

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

Crear instancias de preferencias:

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

2). Para la clase de toda la aplicación, use getApplicationContext() ya que este contexto existe para la vida útil de la aplicación.

Recupere el nombre del paquete actual de Android:

 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; } } 

Enlace una clase de toda la aplicación:

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

3). Para los oyentes y otro tipo de clases de Android (por ejemplo, ContentObserver), use una sustitución de contexto como:

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

donde this o context es el contexto de una clase (Actividad, etc.).

Sustitución del contexto de Activity :

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

Sustitución del contexto del oyente:

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

ContentObserver contexto de ContentObserver :

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

4). Para BroadcastReceiver (incluido el receptor integrado / incrustado), use el contexto del receptor.

External 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); } } } 

BroadcastReceiver incrustado / incrustado:

 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). Para Servicios, use el contexto propio del servicio.

 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). Para Tostadas, generalmente use getApplicationContext() , pero donde sea posible, use el contexto pasado de una Actividad, Servicio, etc.

Usa el contexto de la aplicación:

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

Usar el contexto pasado desde una fuente:

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

Y por último, no use getBaseContext() como lo aconsejan los desarrolladores de framework de Android.

ACTUALIZACIÓN: agregue ejemplos de uso de Context .

Leí este hilo hace unos días y me hice la misma pregunta. Mi decisión después de leer esto fue simple: siempre use applicationContext.

Sin embargo, encontré un problema con esto, pasé unas pocas horas para encontrarlo y unos segundos para resolverlo … (cambiando una palabra …)

Estoy usando un LayoutInflater para inflar una vista que contiene un Spinner.

Entonces aquí hay dos posibilidades:

1)

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

2)

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

Entonces, estoy haciendo algo como esto:

  // 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 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); 

Lo que noté: si instanciaste tu linearLayout con el applicationContext, cuando hagas clic en el spinner de tu actividad, tendrás una excepción no detectada, proveniente de la máquina virtual dalvik (no de tu código, es por eso que he gastado mucho de tiempo para encontrar dónde fue mi error …).

Si usa el baseContext, entonces está bien, se abrirá el menú contextual y podrá elegir entre sus opciones.

Así que aquí está mi conclusión: supongo (no lo he probado más) que el contexto base es necesario cuando se trata de contextMenu en tu actividad …

La prueba ha sido hecha con API 8 y probada en un HTC Desire, Android 2.3.3.

Espero que mi comentario no te haya aburrido hasta ahora y te deseo lo mejor. Feliz encoding 😉

Primero, estoy de acuerdo en que debemos usar el contexto de aplicación siempre que sea posible. luego “esto” en la actividad. Nunca tuve la necesidad de usar el contexto base.

En mis pruebas, en la mayoría de los casos se pueden intercambiar. En la mayoría de los casos, la razón por la que desea obtener un contexto es acceder a archivos, preferencias, bases de datos, etc. Estos datos eventualmente se reflejan como archivos en la carpeta de datos privados de su aplicación (/ data / data /). Independientemente del contexto que use, se asignarán a la misma carpeta / archivos para que esté bien.

Eso es lo que observé. Tal vez hay casos en que debes distinguirlos.

En algunos casos, puede usar el contexto de la actividad sobre el contexto de la aplicación cuando ejecuta algo en un hilo. Cuando el hilo completa la ejecución y necesita devolver el resultado a la actividad de la persona que llama, necesita ese contexto con un controlador.

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

En palabras simples

getApplicationContext() ya que el nombre del método sugerido hará que su aplicación tenga en cuenta los detalles de toda la aplicación a los que puede acceder desde cualquier lugar de la aplicación. De modo que puede utilizar esto en el enlace de servicios, el registro de difusión, etc. El Application context estará activo hasta que la aplicación finalice.

getActivity() o this hará que su aplicación tenga conocimiento de la pantalla actual, que también está visible en los detalles del nivel de la aplicación proporcionados por el application context . Entonces, todo lo que quieras saber sobre la pantalla actual, como Window ActionBar Fragementmanger está disponible en este contexto. Básicamente y Activity ampliar Context . Este contexto seguirá vivo hasta que el componente actual (actividad) esté vivo

Solo he usado esto y getBaseContext al tostar desde un onClick (novato muy verde tanto para Java como para Android). Utilizo esto cuando mi clicker está directamente en la actividad y tengo que usar getBaseContext en un clicker interno anónimo. Supongo que ese es el truco con getBaseContext , quizás devuelva el contexto de la actividad en la que se esconde la clase interna.