Usando o contexto em um fragmento

664

Como posso obter o contexto em um fragmento?

Preciso usar meu banco de dados cujo construtor aceita o contexto, mas, getApplicationContext()e FragmentClass.thisnão funciona, o que posso fazer?

Construtor de banco de dados

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

Respostas:

1313

Você pode usar getActivity(), que retorna a atividade associada a um fragment.
A atividade é uma context (já que Activityse estende Context) .

Nilesh Rathod
fonte
212
getActivity () pode retornar nulo se for chamado antes de onAttach do respectivo fragmento.
precisa saber é o seguinte
4
Eu estava lendo este blog do Google sobre vazamentos de memória ... android-developers.blogspot.com/2009/01/… . Se eu usar o método getActivity (), o aplicativo não correria o risco de vazamento de memória? O blog sugere "Tente usar o aplicativo de contexto em vez de uma atividade de contexto", o que não é realmente possível, pois getApplicationContext () funciona apenas para a classe Activity e não para a classe Fragment.
Simon
40
Uma solução para o problema de fragmentos desanexados é armazenar o valor de getActivity().getApplicationContext()em uma variável de instância quando o fragmento é criado e, em seguida, usar esse contexto sempre que desejar dentro da classe de fragmento. Esse contexto sobreviverá a desapegos de fragmentos.
Piovezan
8
Em vez de passar pelo contexto do aplicativo, crie um contexto estático dentro da classe Application e inicialize-o em OnCreate (): MyApplication.sContext = getApplicationContext (); então você pode acessá-lo de qualquer atividade / fragmento sem se preocupar com desapego.
Eduko 23/02
3
@ milaniez: getActivitysempre esteve disponível. É getContexto que foi adicionado em API 23.
mhsmith
130

Para fazer como a resposta acima, você pode substituir o onAttachmétodo do fragmento:

public static class DummySectionFragment extends Fragment{
...
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        DBHelper = new DatabaseHelper(activity);
    }
}
iambox
fonte
3
Eu recomendaria isso, pois getActivity () retorna nulo se onAttach ainda não foi chamado.
precisa saber é o seguinte
9
Mas, lembre-se, quando onAttach () é chamado, não há visualizações. Portanto, você ainda não pode fazer nada com visualizações!
Zordid
2
@iambox e se DatabaseHelpernecessário um em FragmentActivityvez de um Activity? Por exemplo, para um Adapter...
Jago 19/06
4
Se você armazenar uma referência a sua atividade em onAttach(Activity activity)seguida, você deve liberá-lo emonDetach()
vovahost
3
O onAttachmétodo foi preterido,Overrides deprecated method in 'android.support.v4.app.Fragment'
Muhammad Saqib
24

Sempre use o método getActivity () para obter o contexto de sua atividade anexada, mas lembre-se sempre de uma coisa: os fragmentos são um pouco instáveis ​​e getActivityretornam nulos algumas vezes; portanto, sempre verifique o método isAdded () do fragmento antes de obter o contexto getActivity().

Ankur Chaudhary
fonte
15
Eu não diria que os fragmentos são "um pouco instáveis", parece normal que getActivity () retorne nulo quando o fragmento não pertence a uma atividade. Supõe-se que getActivity () "não retorne nulo" (o que está errado), o que tornaria seu aplicativo (e não a classe Fragment) instável.
que você
3
@ personne3000 Eu gostaria de ouvir mais. Quando um fragmento não pertence a uma atividade? Quando isso está acontecendo e por quê? Devemos verificar isAdded () no fragmento para usar getActivity ()? Alguma regra de ouro?
Sotti 22/04
2
@ Sotti Convido você a criar uma nova pergunta para isso (ou procurar uma já existente), pois esse assunto específico é um pouco diferente da pergunta original. Você pode dar uma olhada em developer.android.com/guide/components/fragments.html#Lifecycle para obter informações gerais. Basicamente, antes de onAttach e depois de onDetach, nenhuma atividade. E entre onAttach e onActivityCreated, o onCreate da atividade ainda não foi chamado. Ao usar getActivity (), verifique se sua atividade já foi criada e pense no que aconteceria se ela fosse destruída ou se seu fragmento fosse desanexado.
que você
22

A maneira mais fácil e precisa de obter o contexto do fragmento que encontrei é obtê-lo diretamente a partir do ViewGroupmomento em que você chamar o onCreateViewmétodo, pelo menos aqui, você tem certeza de que não será nulo por getActivity():

public class Animal extends Fragment { 
  Context thiscontext;
  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
  {
    thiscontext = container.getContext();
Amerdroid
fonte
10
esse é o contexto do contêiner, acho ... não "esse contexto".
Fattie
2
@ AG1, você poderia explicar por que o seu código falhou? Esta é até agora a melhor solução que eu tenho.
Machado
3
Na verdade, em dialogFragments, o contêiner pode ser nulo. Cuidado!
Lucas Teske
Essa solução deve ser usada no onViewCreated, não no onCreateView.
Andrea De Simone
13

Anteriormente eu estou usando onAttach (Activity activity)para chegar contextemFragment

Problema

O onAttach (Activity activity)método foi descontinuado no nível 23 da API.

Solução

Agora, para obter contexto Fragment, podemos usaronAttach (Context context)

onAttach (Context context)

  • Chamado quando um fragmento é anexado pela primeira vez a ele context. onCreate(Bundle)será chamado depois disso.

Documentação

/**
 * 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 AMOSTRA

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

Também podemos usar getActivity()para entrar context, Fragments mas getActivity()podemos retornar nullse o seu fragmentnão estiver atualmente anexado a um pai activity,

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

Você também pode obter o contexto do inflaterparâmetro, ao substituir onCreateView.

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

Outra abordagem alternativa é:

Você pode obter o contexto usando:

getActivity().getApplicationContext();
codercat
fonte
5

para obter o contexto dentro do fragmento será possível usando getActivity():

public Database()
{
    this.context = getActivity();
    DBHelper = new DatabaseHelper(this.context);
}
  • Cuidado, para usar o Activityassociado ao fragmento getActivity(), você pode usá-lo, mas não é recomendável, pois isso causará vazamentos de memória.

Eu acho que uma abordagem melhor deve estar recebendo Activityo onAttach()método:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    context = activity;
}
Jorgesys
fonte
Você não deve usar getActivity em um fragmento para obter uma visualização, a menos que essa visualização faça parte da atividade. Por que você inflaria uma visão em um fragmento e nem sequer faria referência a alguma coisa?
tyczj
Esta resposta é sobre algo diferente, você está falando sobre qual visualização hiearchy procurar por visualizações. Activity.findViewByIdÉ apenas um método de conveniência para procurar uma visualização na visualização de conteúdo registrado dessa atividade (definido setContentView). No exemplo correto, você está chamando View.findViewByIde não Activity.findViewByIdestá chamando o método na visualização raiz correta . Problema totalmente diferente e, obviamente, você não poderá encontrar sua visão em uma pesquisa que não a sustenta.
JHH
3

getContext() veio na API 23. Substitua-o por getActivity () em todo o código.

Veja se ele corrige o erro. Tente usar métodos que estejam entre o nível mínimo e mínimo da API, caso contrário, esse erro ocorrerá.

Naveen
fonte
3

Desde nível API 23 não é getContext(), mas se você quer apoiar as versões mais antigas que você pode usar getActivity().getApplicationContext()enquanto eu ainda recomendo usar a versão apoio do Fragmentque é android.support.v4.app.Fragment.

Androbin
fonte
2

getActivity() é um filho do contexto, de modo que deve funcionar para você

qazimusab
fonte
2

Use fragmentos da Biblioteca de suporte -

android.support.v4.app.Fragment

e depois substituir

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

Dessa forma, você pode ter certeza de que o contexto sempre será um valor não nulo.

lomza
fonte
2

Você tem opções diferentes:

  • Se seu minSDK <= 21, você pode usar getActivity(), pois esse é um Context.
  • Se o seu minSDK for> = 23, você poderá usá-lo getContext().

Se você não precisa oferecer suporte a versões antigas, continue com getContext().

Jorge
fonte
2

Para o Kotlin, você pode usar contextdiretamente em fragmentos. Mas, em alguns casos, você encontrará um erro como

Incompatibilidade de tipos: o tipo inferido é Contexto? mas o contexto era esperado

para isso você pode fazer isso

val ctx = context ?: return
textViewABC.setTextColor(ContextCompat.getColor(ctx, android.R.color.black))
Kishan Solanki
fonte
Obrigado por disponibilizar uma versão do Kotlin, que funciona bem, no entanto, estou tentando obter o Contexto para o Picasso.get (), com ele e ele nunca funciona, tentei tudo o que posso das amostras acima para obter o contexto. Na melhor das hipóteses, recebo esta mensagem - Muitos argumentos foram passados ​​... Por favor, ajude. val ctx = context?: return Picasso.get (ctx) .load (selectedGallery.imageUrl) .placeholder (R.mipmap.ic_launcher) .into (galleryImage)
Ade
@Ade No seu fragmento, tente usar "atividade !!" em vez de "ctx" e deixe-me saber isso ajuda ou não
Kishan Solanki
@ KishanSolanki124. Muito obrigado pela resposta rápida. Tentei sua sugestão, com o mesmo resultado - Ainda não está funcionando. O prompt exato do erro é - Muitos argumentos para diversão pública aberta get (): Picasso !. Esta mensagem me faz pensar, talvez algo mais seja o erro? Felizmente, encontrei uma maneira de seguir em frente com meu trabalho usando Picasso sem ter contexto. Obrigado novamente.
Ade
2

No kotlin, basta usar em activityvez degetActivity()

Abduhafiz
fonte
2

Com a API 29+ no Kotlin, eu tive que fazer

activity?.applicationContext!!

Um exemplo seria

ContextCompat.getColor(activity?.applicationContext!!, R.color.colorAccent),
Tudo é muito
fonte
Contexto! = ApplicationContext
Gabriele Mariotti
1

Idealmente, você não precisa usar globals. O fragmento possui notificações diferentes, sendo uma delas onActivityCreated. Você pode obter a instância da atividade neste evento de ciclo de vida do fragmento.

Então: você pode desreferenciar o fragmento para obter a atividade, o contexto ou o contexto da aplicação como desejar:

this.getActivity()fornecerá o identificador para a atividade this.getContext(), fornecerá o identificador para o contexto this.getActivity().getApplicationContext(), fornecerá o identificador para o contexto do aplicativo. De preferência, você deve usar o contexto do aplicativo ao transmiti-lo para o banco de dados.

user5610809
fonte
1

A maneira mais simples é usar getActivity(). Mas acho que a maior confusão de usar ogetActivity() método para obter o contexto aqui é uma exceção de ponteiro nulo.

Para isso, verifique primeiro com o isAdded()método que determinará se ele foi adicionado ou não e, em seguida, podemos usar o getActivity()para obter o contexto de Activity.

Saubhagya Ranjan Das
fonte
1
Como isso é diferente da resposta de Ankur Chaudhary ?
Peter Mortensen
1

Você pode ligar getActivity()ou,

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

Você pode usar o método getActivity () para obter contexto ou Você pode usar o método getContext ().

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

Espero que ajude!

Rishabh Sharma
fonte
1
Existem outras respostas que fornecem a pergunta do OP e foram publicadas há algum tempo. Ao postar uma resposta, consulte: Como redigir uma boa resposta? , adicione uma nova solução ou uma explicação substancialmente melhor, especialmente ao responder a perguntas mais antigas.
help-info.de
0

O método getContext () ajuda a usar o contexto da classe em uma atividade de fragmento.

Gavine Joyce
fonte
0

Eu acho que você pode usar

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

      Context context = getActivity.getContext();

  }
}
aswinbhim nath
fonte
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
fonte
0

Também você pode usar:

inflater.getContext();

mas eu preferiria usar

getActivity()

ou

getContext
Lurzapps
fonte
0

Eu preciso de contexto para usar o fragmento arrayAdapter IN, quando eu estava usando o erro getActivity, mas quando eu o substituo por getContext, ele funciona para mim

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

Você pode usar getActivity()ougetContext no fragmento.

Documentação

/**
 * 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();
}

e

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

Dica profissional

Verifique sempre, if(getActivity!=null)pois pode ser nulo quando o fragmento não está anexado à atividade. Às vezes, fazer uma operação longa no fragmento (como buscar dados da API restante) leva algum tempo. e se o usuário navegar para outro fragmento. Então, getActivity será nulo. E você receberá o NPE se não o tiver tratado.

Khemraj
fonte
Esta é uma documentação do método getActivity (), apenas para mostrar que eles podem ser nulos. Aqui mHost é instância de FragmentHostCallbackclasse.
Khemraj
0

Em seu fragmento

((Name_of_your_Activity) getActivity()).helper

Em atividade

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

Fragmento interno para amostra kotlin ajudaria alguém

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

se você usar a ligação de dados;

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

Onde bindingView é inicializado em onCreateView como este

private lateinit var bindingView: FragmentBookingHistoryDetailBinding

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

O método requireContext () é a opção mais simples

requireContext()

Exemplo

MyDatabase(requireContext())
JoséAntonio Campillo
fonte