Vi duas práticas gerais para instanciar um novo fragmento em um aplicativo:
Fragment newFragment = new MyFragment();
e
Fragment newFragment = MyFragment.newInstance();
A segunda opção utiliza um método estático newInstance()
e geralmente contém o seguinte método.
public static Fragment newInstance()
{
MyFragment myFragment = new MyFragment();
return myFragment;
}
No começo, pensei que o principal benefício era o fato de poder sobrecarregar o método newInstance () para dar flexibilidade ao criar novas instâncias de um fragmento - mas também poderia fazer isso criando um construtor sobrecarregado para o fragmento.
Perdi alguma coisa?
Quais são os benefícios de uma abordagem sobre a outra? Ou é apenas uma boa prática?
android
android-fragments
Graham Smith
fonte
fonte
Respostas:
Se o Android decidir recriar o seu Fragmento mais tarde, chamará o construtor sem argumentos do seu fragmento. Portanto, sobrecarregar o construtor não é uma solução.
Com isso dito, a maneira de passar as coisas para o seu Fragmento para que elas estejam disponíveis após a recriação de um fragmento pelo Android é passar um pacote para o
setArguments
método.Então, por exemplo, se quiséssemos passar um número inteiro para o fragmento, usaríamos algo como:
E mais tarde no fragmento,
onCreate()
você pode acessar esse número inteiro usando:Este pacote estará disponível mesmo que o fragmento seja recriado de alguma forma pelo Android.
Observe também:
setArguments
só pode ser chamado antes que o fragmento seja anexado à atividade.Essa abordagem também está documentada na referência do desenvolvedor do Android: https://developer.android.com/reference/android/app/Fragment.html
fonte
O único benefício em usar o
newInstance()
que vejo são os seguintes:Você terá um único local em que todos os argumentos usados pelo fragmento poderão ser agrupados e não precisará escrever o código abaixo sempre que instanciar um fragmento.
É uma boa maneira de dizer a outras classes quais argumentos ele espera que funcionem fielmente (embora você deva poder lidar com casos se nenhum argumento estiver agrupado na instância do fragmento).
Então, minha opinião é que usar uma estática
newInstance()
para instanciar um fragmento é uma boa prática.fonte
Há também outra maneira:
fonte
instantiate()
Creates a new instance of a Fragment with the given class name. This is the same as calling its empty constructor.
Enquanto @yydl fornece uma razão convincente para o
newInstance
melhor método:ainda é possível usar um construtor . Para entender por que isso ocorre, primeiro precisamos ver por que a solução alternativa acima é usada pelo Android.
Antes que um fragmento possa ser usado, é necessária uma instância. O Android chama
YourFragment()
(o construtor sem argumentos ) para construir uma instância do fragmento. Aqui, qualquer construtor sobrecarregado que você escreve será ignorado, pois o Android não pode saber qual usar.Durante a vida útil de uma atividade, o fragmento é criado como descrito acima e destruído várias vezes pelo Android. Isso significa que se você colocar dados no próprio objeto de fragmento, eles serão perdidos quando o fragmento for destruído.
Para contornar o problema, o Android solicita que você armazene dados usando uma
Bundle
(chamadasetArguments()
), que pode ser acessada a partir deYourFragment
. Os argumentosbundle
são protegidos pelo Android e, portanto, garantem a persistência .Uma maneira de configurar esse pacote configurável é usando um
newInstance
método estático :No entanto, um construtor:
pode fazer exatamente a mesma coisa que o
newInstance
métodoNaturalmente, isso falharia e é um dos motivos pelos quais o Android quer que você use o
newInstance
método:Como explicação adicional, aqui está a Classe de Fragmentos do Android:
Observe que o Android pede que os argumentos sejam definidos apenas na construção e garante que eles serão mantidos.
EDIT : Como apontado nos comentários de @JHH, se você estiver fornecendo um construtor personalizado que requer alguns argumentos, o Java não fornecerá ao seu fragmento um construtor padrão sem argumento . Portanto, isso exigiria que você definisse um construtor no arg , que é um código que você poderia evitar com o
newInstance
método factory.EDIT : Android não permite mais usar um construtor sobrecarregado para fragmentos. Você deve usar o
newInstance
métodofonte
Não concordo com a resposta do yydi dizendo:
Eu acho que é uma solução e uma boa solução, esse é exatamente o motivo pelo qual foi desenvolvida pela linguagem principal do Java.
É verdade que o sistema Android pode destruir e recriar o seu
Fragment
. Então você pode fazer isso:Isso permitirá que você use a
someInt
partirgetArguments()
de agora, mesmo que tenhaFragment
sido recriado pelo sistema. Esta é uma solução mais elegante que ostatic
construtor.Na minha opinião,
static
construtores são inúteis e não devem ser usados. Eles também o limitarão se, no futuro, você desejar estender issoFragment
e adicionar mais funcionalidade ao construtor. Com ostatic
construtor, você não pode fazer isso.Atualizar:
O Android adicionou uma inspeção que sinaliza todos os construtores não padrão com um erro.
Eu recomendo desativá-lo, pelos motivos mencionados acima.
fonte
Algum código kotlin :
E você pode obter argumentos com isso:
fonte
A melhor prática para instar fragmentos com argumentos no android é ter o método de fábrica estática no seu fragmento.
Você deve evitar definir seus campos com a instância de um fragmento. Porque sempre que o sistema Android recriar seu fragmento, se achar que o sistema precisa de mais memória, ele recriará seu fragmento usando o construtor sem argumentos.
Você pode encontrar mais informações sobre as melhores práticas para instanciar fragmentos com argumentos aqui.
fonte
Como as perguntas sobre as melhores práticas, eu acrescentaria, que muitas vezes é uma boa idéia usar a abordagem híbrida para criar fragmentos ao trabalhar com alguns serviços da web REST
Não podemos passar objetos complexos, por exemplo, algum modelo de usuário, para exibir fragmento de usuário
Mas o que podemos fazer é fazer check-in
onCreate
desse usuário! = Null e, se não - então trazê-lo da camada de dados, caso contrário - use o existente.Dessa forma, obtemos a capacidade de recriar pelo userId em caso de recriação de fragmentos pelo Android e o snappiness para as ações do usuário, bem como a capacidade de criar fragmentos mantendo pressionado para objetar a si próprio ou apenas seu ID
Algo gosta disso:
fonte
User user = /*...*/
coloque o usuário no pacote configurável :Bundle bundle = new Bundle(); bundle.putParcelable("some_user", user);
e obtenha o usuário dos argumentos:User user = getArguments().getParcelable("some_user");
O objeto deve ser implementar a interface Parcelable. linkuse este código 100% corrija seu problema
insira esse código no firstFragment
este exemplo envia dados booleanos
e no SecendFragment
código feliz
fonte
A melhor maneira de instanciar o fragmento é usar o método Fragment.instantiate padrão ou criar o método factory para instanciar o fragmento
Cuidado: sempre crie um construtor vazio no fragmento outro enquanto a restauração do fragmento lançará uma exceção em tempo de execução.
fonte
Ultimamente estou aqui. Mas algumas coisas que eu acabei de saber que podem ajudá-lo um pouco.
Se você estiver usando Java, não há muito o que mudar. Mas para os desenvolvedores do kotlin, aqui estão alguns trechos a seguir que eu acho que podem torná-lo um porão para rodar:
Feliz codificação.
fonte
setArguments()
é inútil. Isso só traz uma bagunça.fonte
onViewCreated
escopo. Acho que é conveniência, muitas maneiras de fazer a mesma coisa. Também é uma maneira fácil de verificar se há atualizações feitas pelo usuário (comparar os pacotes degetArguments
e o pacote deonSaveInstanceState
)getArguments
itens. E quanto aoonViewCreated
escopo ... Podemos restaurar o pacote de estado lá. Mas eu prefiro makeonCreateView
leve e rápido e fazer toda a inicialização pesada dentro de umonActivityCreated
, porqueFragment.getActivity()
às vezes gostaria de voltarnull
e por causa deonAttach()
mudanças na nova versão do API 23.set
eget
Arguments
emsaveInstanceState
. Você está essencialmente fazendo a mesma coisa que é feita "sob o capô"saveInstanceState
é "sob o capô". E usar deArguments
é a duplicação de funcionalidades que fazem com que você verifiqueArguments
novamente : primeiro os valores e depois ossaveInstanceState
valores. Porque você tem que usar desaveInstanceState
qualquer maneira. Que talArguments
... eles não são necessários.Acredito que tenho uma solução muito mais simples para isso.
fonte