Eu tenho um Fragment
com um construtor que leva vários argumentos. Meu aplicativo funcionou bem durante o desenvolvimento, mas, na produção, meus usuários às vezes veem essa falha:
android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment
make sure class name exists, is public, and has an empty constructor that is public
Eu poderia criar um construtor vazio como essa mensagem de erro sugere, mas isso não faz sentido para mim desde então, eu teria que chamar um método separado para concluir a configuração Fragment
.
Estou curioso para saber por que esse acidente ocorre ocasionalmente. Talvez eu esteja usando o ViewPager
incorretamente? Eu instanciar todos os Fragment
s eu mesmo e salvá-los em uma lista dentro do Activity
. Não uso FragmentManager
transações, pois os ViewPager
exemplos que eu vi não exigem isso e tudo parecia funcionar durante o desenvolvimento.
android
android-fragments
stkent
fonte
fonte
Fragment
subclasse não declarar nenhum construtor, por padrão, um construtor público vazio será implicitamente feito para você (esse é o comportamento padrão do Java ). Você não precisa declarar explicitamente um construtor vazio, a menos que tenha declarado outros construtores (por exemplo, aqueles com argumentos).Respostas:
Sim, eles fazem.
Você realmente não deveria substituir o construtor de qualquer maneira. Você deve ter um
newInstance()
método estático definido e passar quaisquer parâmetros por meio de argumentos (pacote configurável)Por exemplo:
E, claro, pegando os argumentos dessa maneira:
Então você instanciaria do seu gerenciador de fragmentos da seguinte forma:
Dessa forma, se desanexado e reconectado, o estado do objeto pode ser armazenado através dos argumentos. Muito parecido com pacotes anexados aos Intents.
Razão - Leitura extra
Eu pensei em explicar o porquê das pessoas que se perguntam o porquê.
Se você marcar: https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/app/Fragment.java
Você verá que o
instantiate(..)
método naFragment
classe chama onewInstance
método:http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#newInstance () Explica por que, por instanciação, verifica se o acessador é
public
e se esse carregador de classes permite acesso a ele.É um método bastante desagradável, mas permite
FragmentManger
matar e recriarFragments
com estados. (O subsistema Android faz coisas semelhantesActivities
).Classe de exemplo
Me perguntam muito sobre ligar
newInstance
. Não confunda isso com o método de classe. Este exemplo de classe inteira deve mostrar o uso.fonte
Conforme observado pelo CommonsWare nesta pergunta https://stackoverflow.com/a/16064418/1319061 , esse erro também pode ocorrer se você estiver criando uma subclasse anônima de um Fragmento, pois as classes anônimas não podem ter construtores.
Não faça subclasses anônimas de Fragment :-)
fonte
Sim, como você pode ver, o pacote de suporte instancia os fragmentos também (quando eles são destruídos e reabertos). Suas
Fragment
subclasses precisam de um construtor público vazio, pois é isso que está sendo chamado pela estrutura.fonte
super()
seria infrutífero, pois a classe pai quebrou a regra do construtor público vazio. Portanto, não, você não precisa passarsuper()
dentro do seu construtor.Aqui está minha solução simples:
1 - Defina seu fragmento
2 - Crie seu novo fragmento e preencha o parâmetro
3 - Aproveite!
Obviamente, você pode alterar o tipo e o número de parâmetros. Rápido e fácil.
fonte