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

Resuelto Alnitak asked hace 54 años • 7 respuestas

En varios fragmentos de 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 sobre cuál es preferible y bajo qué circunstancias debería usarse.

Se agradecerían mucho sugerencias sobre documentación sobre esto y orientación sobre lo que podría romperse si se elige el incorrecto.

Alnitak avatar Jan 01 '70 08:01 Alnitak
Aceptado

Estoy de acuerdo en que la documentación es escasa cuando se trata de Contextos en Android, pero puedes reunir algunos datos de varias fuentes.

Esta publicación en el blog oficial de desarrolladores de Google Android se escribió principalmente para ayudar a abordar las pérdidas de memoria, pero también proporciona buena información sobre los contextos:

En una aplicación normal de Android, normalmente hay dos tipos de Contexto, Actividad y Aplicación.

Leer el artículo un poco más explica la diferencia entre los dos y cuándo es posible que desee considerar usar el contexto de la aplicación ( Activity.getApplicationContext()) en lugar de usar el contexto de actividad 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 su aplicación, mientras que el contexto de la actividad está asociado con la actividad y posiblemente podría destruirse muchas veces a medida que la actividad se destruye durante los cambios de orientación de la pantalla y semejante.

Realmente no pude encontrar nada sobre cuándo usar getBaseContext() aparte de una publicación de Dianne Hackborn, una de las ingenieras de Google que trabaja en el SDK de Android:

No uses getBaseContext(), solo usa el contexto que tienes.

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

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

snctln avatar Jun 22 '2009 14:06 snctln

Esto es lo que encontré con respecto al uso de context:

1). Dentro de un Activitymismo, utilícelo thispara inflar diseños y menús, registrar menús contextuales, crear instancias de widgets, iniciar otras actividades, crear nuevas Intentdentro de un archivo Activity, crear instancias de preferencias u otros métodos disponibles en un archivo Activity.

Diseño de inflado:

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

Registrar menú contextual:

this.registerForContextMenu(myView);

Instanciar widget:

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

Iniciar un Activity:

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

Preferencias de instanciación:

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

2). Para la clase de toda la aplicación, utilícelo getApplicationContext()ya que este contexto existe durante la vida útil de la aplicación.

Recupere el nombre del paquete de Android actual:

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

Vincular una clase para 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 oyentes y otros tipos de clases de Android (por ejemplo, ContentObserver), utilice una sustitución de contexto como:

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

donde thiso contextes el contexto de una clase (Actividad, etc.).

Activitysustitución de contexto:

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

ContentObserversustitución de contexto:

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/en línea), utilice el propio contexto del receptor.

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

En línea/Incrustado 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). Para Servicios, utilice 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 Toasts, generalmente use getApplicationContext(), pero cuando sea posible, use el contexto pasado de una Actividad, Servicio, etc.

Utilice el contexto de la aplicación:

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

Utilice 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 lo utilice getBaseContext()según lo recomendado por los desarrolladores del marco de trabajo de Android.

ACTUALIZACIÓN: agregue ejemplos de Contextuso.

ChuongPham avatar Dec 19 '2012 04:12 ChuongPham