Usando contexto en un fragmento

664

¿Cómo puedo obtener el contexto en un fragmento?

Tengo que usar mi base de datos cuyo constructor toma en el contexto, pero getApplicationContext()y FragmentClass.thisno trabajo así que ¿qué puedo hacer?

Constructor de bases de datos

public Database(Context ctx)
{
    this.context = ctx;
    DBHelper = new DatabaseHelper(context);
}
tyczj
fuente

Respuestas:

1314

Puede usar getActivity(), que devuelve la actividad asociada con a fragment.
La actividad es una context (ya que se Activityextiende Context) .

Nilesh Rathod
fuente
212
getActivity () puede devolver nulo si se llama antes de onAttach del fragmento respectivo.
arne.jans
44
Estaba leyendo este blog de Google sobre pérdidas de memoria ... android-developers.blogspot.com/2009/01/… . Si uso el método getActivity (), ¿la aplicación no correría el riesgo de pérdidas de memoria? El blog sugiere "Intente usar la aplicación de contexto en lugar de una actividad de contexto", lo cual no es realmente posible ya que getApplicationContext () solo funciona para la clase Activity y no para la clase Fragment.
Simon
40
Una solución para el problema de los fragmentos separados es almacenar el valor de getActivity().getApplicationContext()en una variable de instancia cuando se crea el fragmento y luego usar ese contexto siempre que lo desee dentro de la clase de fragmento. Ese contexto sobrevivirá a los desprendimientos de fragmentos.
Piovezan
8
En lugar de pasar por el contexto de la aplicación, cree un contexto estático dentro de su clase de Aplicación e inicialícelo en OnCreate (): MyApplication.sContext = getApplicationContext (); entonces puede acceder desde cualquier actividad / fragmento sin preocuparse por el desprendimiento.
Eduko
3
@milaniez: getActivitysiempre ha estado disponible. Es el getContextque se agregó en la API 23.
mhsmith
130

Para hacer como la respuesta anterior, puede anular el onAttachmétodo de fragmento:

public static class DummySectionFragment extends Fragment{
...
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        DBHelper = new DatabaseHelper(activity);
    }
}
iambox
fuente
3
Recomendaría esto, ya que getActivity () devuelve nulo si todavía no se llama a onAttach.
arne.jans
99
Pero tenga en cuenta que cuando se llama a onAttach (), no hay vistas. ¡Así que no puedes hacer nada con las vistas todavía!
Zordid
2
@iambox, ¿qué pasa si es DatabaseHelpernecesario un en FragmentActivitylugar de un Activity? Por ejemplo, para un Adapter...
Jago
44
Si almacena una referencia a su actividad onAttach(Activity activity), debe publicarla enonDetach()
vovahost el
3
El onAttachmétodo ha quedado en desuso,Overrides deprecated method in 'android.support.v4.app.Fragment'
Muhammad Saqib
24

Siempre use el método getActivity () para obtener el contexto de su actividad adjunta, pero siempre recuerde una cosa: los fragmentos son ligeramente inestables y getActivitydevuelven valores nulos algunas veces, así que para eso, siempre verifique el método de fragmento isAdded () antes de obtener el contexto getActivity().

Ankur Chaudhary
fuente
15
No diría que los fragmentos son "ligeramente inestables", parece bastante normal que getActivity () devuelva nulo cuando el fragmento no pertenece a una actividad. Se supone que getActivity () "no debería devolver nulo" (lo cual está mal) que haría que su aplicación (y no la clase Fragment) sea inestable.
personne3000
3
@ personne3000 Me gustaría saber más. ¿Cuándo un fragmento no pertenece a una actividad? ¿Cuándo sucede esto y por qué? ¿Deberíamos verificar isAdded () en el fragmento para usar getActivity ()? ¿Alguna regla general?
Sotti
2
@Sotti Te animo a crear una nueva pregunta para esto (o buscar una existente), ya que este tema específico es un poco diferente de la pregunta original. Puede consultar developer.android.com/guide/components/fragments.html#Lifecycle para obtener información general. Básicamente, antes de onAttach y después de onDetach, no hay actividad. Y entre onAttach y onActivityCreated, onCreate de la actividad aún no se ha llamado. Cuando use getActivity (), asegúrese de que su actividad ya se haya creado y piense en lo que sucedería si se destruyera o se separara su fragmento.
personne3000
22

La forma más fácil y precisa de obtener el contexto del fragmento que encontré es obtenerlo directamente desde el método ViewGroupcuando llama onCreateView, al menos aquí está seguro de que no quedará nulo para getActivity():

public class Animal extends Fragment { 
  Context thiscontext;
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
  {
    thiscontext = container.getContext();
Amerdroid
fuente
10
ese es el contexto del contenedor, creo ... no "este contexto".
Fattie
2
@ AG1, ¿podría explicar por qué bloqueó su código? Esta es la mejor solución que tengo hasta ahora
Machado
3
En realidad, en dialogFragments, el contenedor puede ser nulo. ¡Ten cuidado!
Lucas Teske
Esta solución debe usarse en onViewCreated, no enCreateView.
Andrea De Simone
13

Anteriormente estoy usando onAttach (Activity activity)para obtener contextenFragment

Problema

El onAttach (Activity activity)método quedó en desuso en el nivel 23 de API.

Solución

Ahora para obtener contexto Fragmentpodemos usaronAttach (Context context)

onAttach (Context context)

  • Se llama cuando un fragmento se une por primera vez a su context. onCreate(Bundle)será llamado después de esto.

Documentación

/**
 * Called when a fragment is first attached to its context.
 * {@link #onCreate(Bundle)} will be called after this.
 */
@CallSuper
public void onAttach(Context context) {
    mCalled = true;
    final Activity hostActivity = mHost == null ? null : mHost.getActivity();
    if (hostActivity != null) {
        mCalled = false;
        onAttach(hostActivity);
    }
}

CÓDIGO DE MUESTRA

public class FirstFragment extends Fragment {


    private Context mContext;
    public FirstFragment() {
        // Required empty public constructor
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mContext=context;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rooView=inflater.inflate(R.layout.fragment_first, container, false);

        Toast.makeText(mContext, "THIS IS SAMPLE TOAST", Toast.LENGTH_SHORT).show();
        // Inflate the layout for this fragment
        return rooView;
    }

}

NOTA

También podemos utilizar getActivity()para conseguir contexten Fragments pero getActivity()podemos volver nullsi el tu fragmentno está conectado actualmente a un padre activity,

Nilesh Rathod
fuente
11
@Override
public void onAttach(Activity activity) {
    // TODO Auto-generated method stub
    super.onAttach(activity);
    context=activity;
}
taran mahal
fuente
6

También puede obtener el contexto del inflaterparámetro, al anularlo onCreateView.

public static class MyFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
        /* ... */
        Context context = inflater.getContext();
        /* ... */
    }
}
luizfls
fuente
5

Otro enfoque alternativo es:

Puede obtener el contexto usando:

getActivity().getApplicationContext();
codercat
fuente
5

para obtener el contexto dentro del Fragmento será posible usando getActivity():

public Database()
{
    this.context = getActivity();
    DBHelper = new DatabaseHelper(this.context);
}
  • Tenga cuidado, para obtener el uso Activityasociado con el fragmento getActivity(), puede usarlo, pero no se recomienda porque causará pérdidas de memoria.

Creo que un mejor enfoque debe ser obtener Activitydel onAttach()método:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    context = activity;
}
Jorgesys
fuente
No debería usar getActivity en un fragmento para obtener una vista, a menos que esa vista sea parte de la actividad de todos modos. ¿Por qué inflar una vista en un fragmento y luego ni siquiera hacer referencia a nada de ella?
tyczj
Esta respuesta es acerca de algo diferente, usted está hablando de en qué jerarquía de vistas buscar vistas. Activity.findViewByIdEs solo un método conveniente para buscar una vista en la vista de contenido registrado de esa actividad (configurada setContentView). En su ejemplo correcto, está llamando View.findViewById, no Activity.findViewById, e invocando el método en la vista raíz correcta . Problema totalmente diferente, y obviamente no podrá encontrar su vista en una jerarquía de vistas que no contenga esa vista.
JHH
3

getContext() vino en API 23. Reemplácelo con getActivity () en todas partes del código.

Vea si soluciona el error. Intente utilizar métodos que se encuentren entre el objetivo y el nivel mínimo de API; de lo contrario, se producirá este error.

Naveen
fuente
3

Desde el nivel 23 de API existe, getContext()pero si desea admitir versiones anteriores, puede usarlo, getActivity().getApplicationContext()pero aún así recomiendo usar la versión de soporte Fragmentque es android.support.v4.app.Fragment.

Androbin
fuente
2

getActivity() es un niño de contexto, por lo que debería funcionar para usted

qazimusab
fuente
2

Usar fragmentos de la Biblioteca de soporte :

android.support.v4.app.Fragment

y luego anular

void onAttach (Context context) {
  this.context = context;
}

De esta manera, puede estar seguro de que el contexto siempre será un valor no nulo.

lomza
fuente
2

Tienes diferentes opciones:

  • Si su minSDK <= 21, puede usarlo getActivity(), ya que este es un Context.
  • Si su minSDK es> = 23, puede usarlo getContext().

Si no necesita admitir versiones antiguas, vaya con getContext().

Jorge
fuente
2

Para Kotlin puede usar contextdirectamente en fragmentos. Pero en algunos casos encontrarás un error como

No coinciden los tipos: ¿el tipo inferido es Contexto? pero se esperaba contexto

para eso puedes hacer esto

val ctx = context ?: return
textViewABC.setTextColor(ContextCompat.getColor(ctx, android.R.color.black))
Kishan Solanki
fuente
Gracias por utilizar una versión de Kotlin, que funciona bien, sin embargo, estoy tratando de obtener Context for Picasso.get (), y nunca funciona, he intentado todo lo que puedo de las muestras anteriores también para obtener contexto. En el mejor de los casos, recibo este mensaje: se han pasado demasiados argumentos ... Por favor, ayuda. val ctx = context?: return Picasso.get (ctx) .load (selectedGallery.imageUrl) .placeholder (R.mipmap.ic_launcher) .into (galleryImage)
Ade
@Ade En tu fragmento, intenta usar "actividad !!" en lugar de "ctx" y hágame saber que ayuda o no
Kishan Solanki
@ KishanSolanki124. Muchas gracias por la rápida respuesta. Intenté su sugerencia, con el mismo resultado: no funciona todavía. El mensaje de error exacto es: Demasiados argumentos para la diversión pública abierta get (): Picasso !. Este mensaje me hace pensar, ¿quizás algo más es el error? Sin embargo, con mucho gusto, encontré una manera de seguir adelante con mi trabajo utilizando Picasso sin tener contexto. Gracias de nuevo.
Ade
2

En kotlin solo use en activitylugar degetActivity()

Abduhafiz
fuente
2

Con API 29+ en Kotlin, tuve que hacer

activity?.applicationContext!!

Un ejemplo sería

ContextCompat.getColor(activity?.applicationContext!!, R.color.colorAccent),
Todo es variado
fuente
Context! = ApplicationContext
Gabriele Mariotti
1

Idealmente, no debería necesitar usar globals. El fragmento tiene notificaciones diferentes, una de ellas enActivityCreated. Puede obtener la instancia de la actividad en este evento de ciclo de vida del fragmento.

Luego: puede desreferenciar el fragmento para obtener actividad, contexto o contexto de aplicación como desee:

this.getActivity()le dará el identificador de la actividad this.getContext()le dará un identificador del contexto this.getActivity().getApplicationContext()le dará el identificador del contexto de la aplicación. Preferiblemente debe usar el contexto de la aplicación al pasarlo a la base de datos.

usuario5610809
fuente
1

La forma simple es usar getActivity(). Pero creo que la mayor confusión de usar el getActivity()método para obtener el contexto aquí es una excepción de puntero nulo.

Para esto, primero verifique con el isAdded()método que determinará si se agrega o no, y luego podemos usar el getActivity()para obtener el contexto de Actividad.

Saubhagya Ranjan Das
fuente
1
¿Cómo es esto diferente de la respuesta de Ankur Chaudhary ?
Peter Mortensen el
1

Puedes llamar getActivity()o,

public void onAttach(Context context) {
    super.onAttach(context);
    this.activity = (CashActivity) context;
    this.money = this.activity.money;
}
蔡健烽
fuente
1

Puede usar el método getActivity () para obtener contexto o puede usar el método getContext ().

 View root = inflater.inflate(R.layout.fragment_slideshow, container, false);
    Context c = root.getContext();

¡Espero que ayude!

Rishabh Sharma
fuente
1
Hay otras respuestas que proporcionan la pregunta del OP, y se publicaron hace algún tiempo. Cuando publique una respuesta, vea: ¿Cómo escribo una buena respuesta? , asegúrese de agregar una nueva solución o una explicación sustancialmente mejor, especialmente al responder preguntas anteriores.
help-info.de
0

El método getContext () ayuda a usar el contexto de la clase en una actividad de fragmento.

Gavine Joyce
fuente
0

Creo que puedes usar

public static class MyFragment extends Fragment {
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

      Context context = getActivity.getContext();

  }
}
aswinbhim nath
fuente
0
public class MenuFragment extends Fragment implements View.OnClickListener {
    private Context mContext;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        FragmentMenuBinding binding=FragmentMenuBinding.inflate(inflater,container,false);
        View view=binding.getRoot();
        mContext=view.getContext();
        return view;
    }
}
Mohsinali
fuente
0

También puedes usar:

inflater.getContext();

pero preferiría usar

getActivity()

o

getContext
Lurzapps
fuente
0

Necesito contexto para usar el fragmento de arrayAdapter IN, cuando estaba usando el error getActivity ocurre pero cuando lo reemplazo con getContext funciona para mí

listView LV=getView().findViewById(R.id.listOFsensors);
LV.setAdapter(new ArrayAdapter<String>(getContext(),android.R.layout.simple_list_item_1 ,listSensorType));
ghazaleh javaheri
fuente
0

Puedes usar getActivity()o getContexten Fragment.

Documentación

/**
 * Return the {@link FragmentActivity} this fragment is currently associated with.
 * May return {@code null} if the fragment is associated with a {@link Context}
 * instead.
 *
 * @see #requireActivity()
 */
@Nullable
final public FragmentActivity getActivity() {
    return mHost == null ? null : (FragmentActivity) mHost.getActivity();
}

y

 /**
     * Return the {@link Context} this fragment is currently associated with.
     *
     * @see #requireContext()
     */
    @Nullable
    public Context getContext() {
        return mHost == null ? null : mHost.getContext();
    }

Consejo profesional

Compruebe siempre if(getActivity!=null)porque puede ser nulo cuando el fragmento no está asociado a la actividad. A veces, realizar operaciones largas en fragmentos (como recuperar datos de la API de descanso) lleva algún tiempo. y si el usuario navega a otro fragmento. Entonces getActivity será nulo. Y obtendrá NPE si no lo manejó.

Khemraj
fuente
Esta es una documentación del método getActivity (), solo para mostrar que estos pueden ser nulos. Aquí mHost es una instancia de FragmentHostCallbackclase.
Khemraj
0

En tu fragmento

((Name_of_your_Activity) getActivity()).helper

En la actividad

DbHelper helper = new DbHelper(this);
Kinggeov
fuente
0

El fragmento interior para la muestra de Kotlin ayudaría a alguien

textViewStatus.setTextColor(ContextCompat.getColor(context!!, R.color.red))

si usa enlace de datos;

bindingView.textViewStatus.setTextColor(ContextCompat.getColor(context!!, R.color.red))

Donde vinculanteView se inicializa en onCreateView como este

private lateinit var bindingView: FragmentBookingHistoryDetailBinding

bindingView = DataBindingUtil.inflate(inflater, R.layout.your_layout_xml, container, false)
Shihab Uddin
fuente
0

El método requireContext () es la opción más simple

requireContext()

Ejemplo

MyDatabase(requireContext())
José Antonio Campillo
fuente