Eu tenho um fragmento (F1) com um método público como este
public void asd() {
if (getActivity() == null) {
Log.d("yes","it is null");
}
}
e sim quando eu chamo (da Activity), é nulo ...
FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
F1 f1 = new F1();
transaction1.replace(R.id.upperPart, f1);
transaction1.commit();
f1.asd();
Devo estar fazendo algo muito errado, mas não sei o que é isso
getActivity()
. Além disso, como você está instanciando o fragmento? Você o possui em seu layout.xml?Respostas:
commit
agenda a transação, ou seja, isso não acontece imediatamente, mas é agendado como trabalho no encadeamento principal na próxima vez que o encadeamento principal estiver pronto.Eu sugiro adicionar um
método para o seu
Fragment
e colocando um ponto de interrupção nele e vendo quando é chamado em relação à sua chamada paraasd()
. Você verá que ele é chamado após o método em que você faz a chamada paraasd()
saídas. AonAttach
chamada é ondeFragment
está anexado à sua atividade e a partir deste pontogetActivity()
retornará não nulo (nb também há umaonDetach()
chamada).fonte
onCreateView
ouonActivityCreated
métodos. Eu questiono por que asd () precisa ser chamado quando isso ocorre na publicação de perguntas.commitNow()
O melhor para se livrar disso é manter a referência da atividade quando onAttach for chamado e usar a referência da atividade sempre que necessário, por exemplo
fonte
onDestroy()
eonDetach()
porqueonDestroy()
não é garantido que seja chamado.Activity
se não o anularmosonDestroy()
?Isso aconteceu quando você chama
getActivity()
outro segmento que terminou após a remoção do fragmento. O caso típico é chamargetActivity()
(por exemplo, aToast
) quando uma solicitação HTTP é concluída (onResponse
por exemplo).Para evitar isso, você pode definir um nome de campo
mActivity
e usá-lo em vez degetActivity()
. Este campo pode ser inicializado no método onAttach () do Fragment da seguinte maneira:Nos meus projetos, geralmente defino uma classe base para todos os meus fragmentos com este recurso:
Feliz codificação,
fonte
Activity
de outro segmento. Você não pode fazer nada com isso de qualquer maneira, nem mesmo mostrar um brinde. Portanto, você deve transferir o trabalho para o encadeamento principal primeiro ou não usar a Atividade.As outras respostas que sugerem manter uma referência à atividade no onAttach estão apenas sugerindo uma bandaid para o problema real. Quando getActivity retorna nulo, significa que o Fragmento não está anexado à Atividade. Geralmente, isso acontece quando a atividade desaparece devido à rotação ou à conclusão da atividade, mas o fragmento ainda possui algum tipo de ouvinte de retorno de chamada registrado. Quando o ouvinte é chamado, se você precisar fazer algo com a Atividade, mas a Atividade se foi, não há muito o que fazer. No seu código, você deve apenas verificar
getActivity() != null
e se não estiver lá, não faça nada. Se você mantiver uma referência à Atividade que se foi, estará impedindo a coleta de lixo da Atividade. Quaisquer coisas da interface do usuário que você tente fazer não serão vistas pelo usuário. Posso imaginar algumas situações em que, no ouvinte de retorno de chamada, você pode querer ter um contexto para algo não relacionado à interface do usuário; nesses casos, provavelmente faz mais sentido obter o contexto do aplicativo. Observe que o único motivo pelo qualonAttach
truque não é um grande vazamento de memória é porque, normalmente, depois que o ouvinte de retorno de chamada é executado, ele não é mais necessário e pode ser coletado como lixo junto com o Fragmento, todas as suas visões e o contexto de Atividade. Se vocêssetRetainInstance(true)
há uma chance maior de vazamento de memória porque o campo Atividade também será retido, mas após a rotação que poderia ser a Atividade anterior, não a atual.fonte
Desde o nível 23 da API do Android, onAttach (atividade de atividade) foi preterido. Você precisa usar onAttach (contexto de contexto). http://developer.android.com/reference/android/app/Fragment.html#onAttach(android.app.Activity)
Atividade é um contexto, portanto, se você pode simplesmente verificar se o contexto é uma Atividade e transmiti-lo, se necessário.
fonte
PJL está certo. Eu usei sua sugestão e é isso que eu fiz:
variáveis globais definidas para o fragmento:
private final Object attachingActivityLock = new Object();
private boolean syncVariable = false;
implementado
3) Eu encerrei minha função, onde eu preciso chamar getActivity (), no thread, porque se ele fosse executado no thread principal, eu bloqueava o thread com a etapa 4. e onAttach () nunca seria chamado.
4) na minha função onde eu preciso chamar getActivity (), eu uso isso (antes da chamada getActivity ())
Se você tiver algumas atualizações da interface do usuário, lembre-se de executá-las no thread da interface do usuário. Preciso atualizar o ImgeView, então fiz:
fonte
A ordem na qual os retornos de chamada são chamados após commit ():
Eu precisava fazer algum trabalho que envolvesse algumas Views, portanto onAttach () não funcionou para mim; isso quebrou. Então mudei parte do meu código que estava definindo alguns parâmetros dentro de um método chamado logo após commit () (1.), depois a outra parte do código que manipulava a exibição dentro de onCreateView () (3.).
fonte
Estou usando o OkHttp e acabei de enfrentar esse problema.
Para a primeira parte, @thucnguyen estava no caminho certo .
Algumas chamadas HTTP estavam sendo executadas mesmo após o fechamento da atividade (porque pode demorar um pouco para que uma solicitação HTTP seja concluída). Eu então, através do
HttpCallback
tentou atualizar alguns campos de fragmento e tem umanull
exceção ao tentargetActivity()
.Na IMO, a solução é impedir que retornos de chamada ocorram quando o fragmento não estiver mais ativo (e isso não ocorre apenas com o Okhttp).
A correção: prevenção.
Se você der uma olhada no ciclo de vida do fragmento (mais informações aqui ), notará que há
onAttach(Context context)
eonDetach()
métodos. Eles são chamados após o Fragmento pertencer a uma atividade e pouco antes de deixarem de ser, respectivamente.Isso significa que podemos impedir que esse retorno de chamada ocorra controlando-o no
onDetach
métodofonte
Onde você chama essa função? Se você chamá-lo no construtor de
Fragment
, ele retornaránull
.Basta ligar
getActivity()
quando o métodoonCreateView()
for executado.fonte
Faça o seguinte. Eu acho que será útil para você.
fonte
Aqueles que ainda têm problemas com onAttach (atividade de atividade), acabam de mudar para Contexto -
Na maioria dos casos, salvar o contexto será suficiente para você - por exemplo, se você quiser fazer getResources (), poderá fazê-lo diretamente do contexto. Se você ainda precisar transformar o contexto em sua Atividade, faça isso -
Conforme sugerido pelo usuário1868713.
fonte
Você pode usar onAttach ou se não quiser colocar onAttach em qualquer lugar, poderá colocar um método que retorne ApplicationContext na classe principal do aplicativo:
Depois disso, você pode reutilizá-lo em qualquer lugar do seu projeto, assim:
Informe-me se isso não funcionar para você.
fonte
Outra boa solução seria usar o LiveData do Android com arquitetura MVVM. Você definiria um objeto LiveData dentro do seu ViewModel e o observaria no seu fragmento. Quando o valor do LiveData for alterado, ele notificará o observador (fragmento neste caso) apenas se o fragmento estiver no estado ativo, garantindo assim que você faria sua interface do usuário funcionar e acessaria a atividade somente quando seu fragmento estiver no estado ativo. Essa é uma vantagem que vem com o LiveData
Obviamente, quando essa pergunta foi feita pela primeira vez, não havia LiveData. Estou deixando essa resposta aqui porque, como vejo, ainda existe esse problema e pode ser útil para alguém.
fonte
Chame o método getActivity () dentro do onActivityCreated ()
fonte