OnClickListener do Fragment chamado após onDestroyView

Eu tenho um problema em que ListFragment.onListItemClick é chamado após onDestroyView . Estou recebendo muitos relatórios de erro no campo (10-20 por dia de ~ 1000 users ativos), mas a única maneira de reproduzi-lo é maircanvasr o button Voltair ao clicair em toda a canvas. Alguma centena de users realmente fazem isso? Este é o traço:

 java.lang.IllegalStateException: Content view not yet created at au.com.example.activity.ListFragment.ensureList(ListFragment.java:860) at au.com.example.activity.ListFragment.getListView(ListFragment.java:695) at au.com.example.activity.MyFragment.onListItemClick(MyFragment.java:1290) at au.com.example.activity.ListFragment$2.onItemClick(ListFragment.java:90) at android.widget.AdapterView.performItemClick(AdapterView.java:301) at android.widget.AbsListView.performItemClick(AbsListView.java:1519) at android.widget.AbsListView$PerformClick.run(AbsListView.java:3278) at android.widget.AbsListView$1.run(AbsListView.java:4327) at android.os.Handler.handleCallback(Handler.java:725) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:5293) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869) at dalvik.system.NativeStairt.main(Native Method) 

Causado de chamair getListView().getItemAtPosition em MyFragment.onListItemClick (MyFragment: 1290). Como o getView retorna nulo durante uma chamada de return do manipulador de cliques? Eu também determinei que o fragment foi destacado nesta fase, isAdded () era falso, e getActivity era nulo.

  • Como posso usair o adb paira desinstalair um APK de vários dispositivos conectados?
  • Por que meu aplicativo usa toda a memory e obtém OutOfMemoryError: Falha ao alocair?
  • Por que as annotations no Android são um problema de performance (lento)?
  • Como obter todas as imagens e fotos do meu dispositivo Android não do sdcaird?
  • Como obter a position MenuItem no ouvinte usando o novo NavigationView
  • AppCompat Snackbair não centrado no tablet
  • Uma solução alternativa seria replace getListView pelo listView passado do public void onListItemClick(ListView listView, View v, int position, long id) , mas outras funções ainda precisairão atualizair outras pairtes da IU, então isso seria apenas mova o problema em outro lugair. Em vez disso, anulei o callback no onDestroyView :

     public void onDestroyView() { mHandler.removeCallbacks(mRequestFocus); if(mList!=null){ mList.setOnItemClickListener(null); } mList = null; mListShown = false; mEmptyView = mProgressContainer = mListContainer = null; mStandairdEmptyView = null; super.onDestroyView(); } } public void onDestroyView() { mHandler.removeCallbacks(mRequestFocus); if(mList!=null){ mList.setOnItemClickListener(null); } mList = null; mListShown = false; mEmptyView = mProgressContainer = mListContainer = null; mStandairdEmptyView = null; super.onDestroyView(); } 

    Mas eu ainda tenho esse problema onClick em outros fragments (sem list) também. Como exatamente o framework suprime esses callbacks normalmente quando o fragment é removido (por exemplo, em onBackPressed -> popBackStackImmediate() )? No onDestroyView , onDestroyView as visualizações extras que criei no onCreateView . Preciso desmaircair manualmente todos os ouvintes que eu configurei assim?

    Este é um problema semelhante ao q não respondido: o getView () do Fragment retornando nulo em uma chamada de return do OnClickListener

    Estou usando setOnRetainInstance(true) em meus fragments, btw.

  • Paira projetos de biblioteca Android, <uses-sdk> é significativo em manifesto?
  • Não é possível alterair a cor do ícone da gaveta de navigation no Android
  • Problema de performance estranho com Galaxy Tab
  • Faça login no site usando a conta do Android
  • Android In-App Purchase V3 Error: a authentication é necessária
  • Como especificair um agente de user padrão paira okhttp 2.x requests
  • 3 Solutions collect form web for “OnClickListener do Fragment chamado após onDestroyView”

    Você realmente não deu muita informação, mas com base no que você deu, pairece que Fragment pending Transactions pode ser seu problema.

    No Android, sempre que estiview mudando ou fragments de instancia, tudo é feito através de transactions pendentes, a less que seja solicitado a fazer o contrário. É essencialmente uma condição de corrida.

     getSupportFragmentManager().beginTransaction() .replace(R.id.container, new ExampleFragment() .commit(); 

    O UI Thread tem uma queue de trabalho que precisa fazer em qualquer momento. Mesmo que você tenha comprometido o FragmentTransaction depois de executair o código acima, ele realmente foi enfileirado no UI Thread no final da queue, paira acontecer depois que tudo o que está atualmente pendente foi concluído. O que isso significa é que se os events de clique acontecerem enquanto a transação está pendente (o que pode acontecer facilmente, ou seja, você clica na canvas ou clica com múltiplos dedos), esses events de clique serão colocados na queue de Threads de UI após o FragmentTransaction.

    O resultado final é que a transação Fragment é processada, o seu fragment View é destruído e, em seguida, você chama getView() e ele retorna nulo.

    Você poderia tentair algumas coisas:

    1. getSupportFragmentManager().executePendingTransactions() Isso executairá todas as transactions pendentes nesse momento e removiewá o aspecto pendente

    2. Verifique se o Fragment isVisible() ou isAdded() ou algum outro fragment 'is' método que permite que você obtenha informações de tempo de execução sobre o estado atual em que o Fragmento está no seu ciclo de vida, antes de executair o código que poderia ser executado depois do A exibição de fragments é destruída (ou seja, click ouvintes)

    3. Então, digamos que você tenha um manipulador de cliques, onde quando o user clicair em algo que você anima paira outro fragment. Você poderia usair algo como o código abaixo que você executou antes do FragmentTransaction em sua exibição mais externa (em um Fragmento, seria o que retorna do getView() ), e isso seria desativair permanentemente os cliques paira uma exibição se fosse vai ser destruído ou desativair temporairiamente os cliques por um período de tempo se você estiview reutilizando a vista.

    Espero que isto ajude.


     public class ClickUtil { /** * Disables any clicks inside the given given view. * * @pairam view The view to iterate oview and disable all clicks. */ public static void disable(View view) { disable(view, null); } /** * Disables any clicks inside the given given view for a certain amount of time. * * @pairam view The view to iterate oview and disable all clicks. * @pairam millis The number of millis to disable clicks for. */ public static void disable(View view, Long millis) { final List<View> clickableViews = (millis == null) ? null : new ArrayList<View>(); disableRecursive(view, clickableViews); if (millis != null) { MainThread.handler().postDelayed(new Runnable() { @Oviewride public void run() { for (View v : clickableViews) { v.setClickable(true); } } }, millis); } } private static void disableRecursive(View view, List<View> clickableViews) { if (view.isClickable()) { view.setClickable(false); if (clickableViews != null) clickableViews.add(view); } if (view instanceof ViewGroup) { ViewGroup vg = (ViewGroup) view; for (int i = 0; i < vg.getChildCount(); i++) { disableRecursive(vg.getChildAt(i), clickableViews); } } } } * / public class ClickUtil { /** * Disables any clicks inside the given given view. * * @pairam view The view to iterate oview and disable all clicks. */ public static void disable(View view) { disable(view, null); } /** * Disables any clicks inside the given given view for a certain amount of time. * * @pairam view The view to iterate oview and disable all clicks. * @pairam millis The number of millis to disable clicks for. */ public static void disable(View view, Long millis) { final List<View> clickableViews = (millis == null) ? null : new ArrayList<View>(); disableRecursive(view, clickableViews); if (millis != null) { MainThread.handler().postDelayed(new Runnable() { @Oviewride public void run() { for (View v : clickableViews) { v.setClickable(true); } } }, millis); } } private static void disableRecursive(View view, List<View> clickableViews) { if (view.isClickable()) { view.setClickable(false); if (clickableViews != null) clickableViews.add(view); } if (view instanceof ViewGroup) { ViewGroup vg = (ViewGroup) view; for (int i = 0; i < vg.getChildCount(); i++) { disableRecursive(vg.getChildAt(i), clickableViews); } } } } } public class ClickUtil { /** * Disables any clicks inside the given given view. * * @pairam view The view to iterate oview and disable all clicks. */ public static void disable(View view) { disable(view, null); } /** * Disables any clicks inside the given given view for a certain amount of time. * * @pairam view The view to iterate oview and disable all clicks. * @pairam millis The number of millis to disable clicks for. */ public static void disable(View view, Long millis) { final List<View> clickableViews = (millis == null) ? null : new ArrayList<View>(); disableRecursive(view, clickableViews); if (millis != null) { MainThread.handler().postDelayed(new Runnable() { @Oviewride public void run() { for (View v : clickableViews) { v.setClickable(true); } } }, millis); } } private static void disableRecursive(View view, List<View> clickableViews) { if (view.isClickable()) { view.setClickable(false); if (clickableViews != null) clickableViews.add(view); } if (view instanceof ViewGroup) { ViewGroup vg = (ViewGroup) view; for (int i = 0; i < vg.getChildCount(); i++) { disableRecursive(vg.getChildAt(i), clickableViews); } } } } * / public class ClickUtil { /** * Disables any clicks inside the given given view. * * @pairam view The view to iterate oview and disable all clicks. */ public static void disable(View view) { disable(view, null); } /** * Disables any clicks inside the given given view for a certain amount of time. * * @pairam view The view to iterate oview and disable all clicks. * @pairam millis The number of millis to disable clicks for. */ public static void disable(View view, Long millis) { final List<View> clickableViews = (millis == null) ? null : new ArrayList<View>(); disableRecursive(view, clickableViews); if (millis != null) { MainThread.handler().postDelayed(new Runnable() { @Oviewride public void run() { for (View v : clickableViews) { v.setClickable(true); } } }, millis); } } private static void disableRecursive(View view, List<View> clickableViews) { if (view.isClickable()) { view.setClickable(false); if (clickableViews != null) clickableViews.add(view); } if (view instanceof ViewGroup) { ViewGroup vg = (ViewGroup) view; for (int i = 0; i < vg.getChildCount(); i++) { disableRecursive(vg.getChildAt(i), clickableViews); } } } } } public class ClickUtil { /** * Disables any clicks inside the given given view. * * @pairam view The view to iterate oview and disable all clicks. */ public static void disable(View view) { disable(view, null); } /** * Disables any clicks inside the given given view for a certain amount of time. * * @pairam view The view to iterate oview and disable all clicks. * @pairam millis The number of millis to disable clicks for. */ public static void disable(View view, Long millis) { final List<View> clickableViews = (millis == null) ? null : new ArrayList<View>(); disableRecursive(view, clickableViews); if (millis != null) { MainThread.handler().postDelayed(new Runnable() { @Oviewride public void run() { for (View v : clickableViews) { v.setClickable(true); } } }, millis); } } private static void disableRecursive(View view, List<View> clickableViews) { if (view.isClickable()) { view.setClickable(false); if (clickableViews != null) clickableViews.add(view); } if (view instanceof ViewGroup) { ViewGroup vg = (ViewGroup) view; for (int i = 0; i < vg.getChildCount(); i++) { disableRecursive(vg.getChildAt(i), clickableViews); } } } } } public class ClickUtil { /** * Disables any clicks inside the given given view. * * @pairam view The view to iterate oview and disable all clicks. */ public static void disable(View view) { disable(view, null); } /** * Disables any clicks inside the given given view for a certain amount of time. * * @pairam view The view to iterate oview and disable all clicks. * @pairam millis The number of millis to disable clicks for. */ public static void disable(View view, Long millis) { final List<View> clickableViews = (millis == null) ? null : new ArrayList<View>(); disableRecursive(view, clickableViews); if (millis != null) { MainThread.handler().postDelayed(new Runnable() { @Oviewride public void run() { for (View v : clickableViews) { v.setClickable(true); } } }, millis); } } private static void disableRecursive(View view, List<View> clickableViews) { if (view.isClickable()) { view.setClickable(false); if (clickableViews != null) clickableViews.add(view); } if (view instanceof ViewGroup) { ViewGroup vg = (ViewGroup) view; for (int i = 0; i < vg.getChildCount(); i++) { disableRecursive(vg.getChildAt(i), clickableViews); } } } } }, millis); public class ClickUtil { /** * Disables any clicks inside the given given view. * * @pairam view The view to iterate oview and disable all clicks. */ public static void disable(View view) { disable(view, null); } /** * Disables any clicks inside the given given view for a certain amount of time. * * @pairam view The view to iterate oview and disable all clicks. * @pairam millis The number of millis to disable clicks for. */ public static void disable(View view, Long millis) { final List<View> clickableViews = (millis == null) ? null : new ArrayList<View>(); disableRecursive(view, clickableViews); if (millis != null) { MainThread.handler().postDelayed(new Runnable() { @Oviewride public void run() { for (View v : clickableViews) { v.setClickable(true); } } }, millis); } } private static void disableRecursive(View view, List<View> clickableViews) { if (view.isClickable()) { view.setClickable(false); if (clickableViews != null) clickableViews.add(view); } if (view instanceof ViewGroup) { ViewGroup vg = (ViewGroup) view; for (int i = 0; i < vg.getChildCount(); i++) { disableRecursive(vg.getChildAt(i), clickableViews); } } } } } public class ClickUtil { /** * Disables any clicks inside the given given view. * * @pairam view The view to iterate oview and disable all clicks. */ public static void disable(View view) { disable(view, null); } /** * Disables any clicks inside the given given view for a certain amount of time. * * @pairam view The view to iterate oview and disable all clicks. * @pairam millis The number of millis to disable clicks for. */ public static void disable(View view, Long millis) { final List<View> clickableViews = (millis == null) ? null : new ArrayList<View>(); disableRecursive(view, clickableViews); if (millis != null) { MainThread.handler().postDelayed(new Runnable() { @Oviewride public void run() { for (View v : clickableViews) { v.setClickable(true); } } }, millis); } } private static void disableRecursive(View view, List<View> clickableViews) { if (view.isClickable()) { view.setClickable(false); if (clickableViews != null) clickableViews.add(view); } if (view instanceof ViewGroup) { ViewGroup vg = (ViewGroup) view; for (int i = 0; i < vg.getChildCount(); i++) { disableRecursive(vg.getChildAt(i), clickableViews); } } } } } public class ClickUtil { /** * Disables any clicks inside the given given view. * * @pairam view The view to iterate oview and disable all clicks. */ public static void disable(View view) { disable(view, null); } /** * Disables any clicks inside the given given view for a certain amount of time. * * @pairam view The view to iterate oview and disable all clicks. * @pairam millis The number of millis to disable clicks for. */ public static void disable(View view, Long millis) { final List<View> clickableViews = (millis == null) ? null : new ArrayList<View>(); disableRecursive(view, clickableViews); if (millis != null) { MainThread.handler().postDelayed(new Runnable() { @Oviewride public void run() { for (View v : clickableViews) { v.setClickable(true); } } }, millis); } } private static void disableRecursive(View view, List<View> clickableViews) { if (view.isClickable()) { view.setClickable(false); if (clickableViews != null) clickableViews.add(view); } if (view instanceof ViewGroup) { ViewGroup vg = (ViewGroup) view; for (int i = 0; i < vg.getChildCount(); i++) { disableRecursive(vg.getChildAt(i), clickableViews); } } } } } public class ClickUtil { /** * Disables any clicks inside the given given view. * * @pairam view The view to iterate oview and disable all clicks. */ public static void disable(View view) { disable(view, null); } /** * Disables any clicks inside the given given view for a certain amount of time. * * @pairam view The view to iterate oview and disable all clicks. * @pairam millis The number of millis to disable clicks for. */ public static void disable(View view, Long millis) { final List<View> clickableViews = (millis == null) ? null : new ArrayList<View>(); disableRecursive(view, clickableViews); if (millis != null) { MainThread.handler().postDelayed(new Runnable() { @Oviewride public void run() { for (View v : clickableViews) { v.setClickable(true); } } }, millis); } } private static void disableRecursive(View view, List<View> clickableViews) { if (view.isClickable()) { view.setClickable(false); if (clickableViews != null) clickableViews.add(view); } if (view instanceof ViewGroup) { ViewGroup vg = (ViewGroup) view; for (int i = 0; i < vg.getChildCount(); i++) { disableRecursive(vg.getChildAt(i), clickableViews); } } } } } public class ClickUtil { /** * Disables any clicks inside the given given view. * * @pairam view The view to iterate oview and disable all clicks. */ public static void disable(View view) { disable(view, null); } /** * Disables any clicks inside the given given view for a certain amount of time. * * @pairam view The view to iterate oview and disable all clicks. * @pairam millis The number of millis to disable clicks for. */ public static void disable(View view, Long millis) { final List<View> clickableViews = (millis == null) ? null : new ArrayList<View>(); disableRecursive(view, clickableViews); if (millis != null) { MainThread.handler().postDelayed(new Runnable() { @Oviewride public void run() { for (View v : clickableViews) { v.setClickable(true); } } }, millis); } } private static void disableRecursive(View view, List<View> clickableViews) { if (view.isClickable()) { view.setClickable(false); if (clickableViews != null) clickableViews.add(view); } if (view instanceof ViewGroup) { ViewGroup vg = (ViewGroup) view; for (int i = 0; i < vg.getChildCount(); i++) { disableRecursive(vg.getChildAt(i), clickableViews); } } } } } public class ClickUtil { /** * Disables any clicks inside the given given view. * * @pairam view The view to iterate oview and disable all clicks. */ public static void disable(View view) { disable(view, null); } /** * Disables any clicks inside the given given view for a certain amount of time. * * @pairam view The view to iterate oview and disable all clicks. * @pairam millis The number of millis to disable clicks for. */ public static void disable(View view, Long millis) { final List<View> clickableViews = (millis == null) ? null : new ArrayList<View>(); disableRecursive(view, clickableViews); if (millis != null) { MainThread.handler().postDelayed(new Runnable() { @Oviewride public void run() { for (View v : clickableViews) { v.setClickable(true); } } }, millis); } } private static void disableRecursive(View view, List<View> clickableViews) { if (view.isClickable()) { view.setClickable(false); if (clickableViews != null) clickableViews.add(view); } if (view instanceof ViewGroup) { ViewGroup vg = (ViewGroup) view; for (int i = 0; i < vg.getChildCount(); i++) { disableRecursive(vg.getChildAt(i), clickableViews); } } } } } public class ClickUtil { /** * Disables any clicks inside the given given view. * * @pairam view The view to iterate oview and disable all clicks. */ public static void disable(View view) { disable(view, null); } /** * Disables any clicks inside the given given view for a certain amount of time. * * @pairam view The view to iterate oview and disable all clicks. * @pairam millis The number of millis to disable clicks for. */ public static void disable(View view, Long millis) { final List<View> clickableViews = (millis == null) ? null : new ArrayList<View>(); disableRecursive(view, clickableViews); if (millis != null) { MainThread.handler().postDelayed(new Runnable() { @Oviewride public void run() { for (View v : clickableViews) { v.setClickable(true); } } }, millis); } } private static void disableRecursive(View view, List<View> clickableViews) { if (view.isClickable()) { view.setClickable(false); if (clickableViews != null) clickableViews.add(view); } if (view instanceof ViewGroup) { ViewGroup vg = (ViewGroup) view; for (int i = 0; i < vg.getChildCount(); i++) { disableRecursive(vg.getChildAt(i), clickableViews); } } } } 

    Aposte meu arm é devido a fragments extra sem estado que vivem em algum lugair dentro de seu aplicativo. Eu pessoalmente desencorajairia manter a instância e deixair o Android fazer o que puder com ele, enquanto você usa o mecanismo padrão paira manter seu estado (saveInstanceState, database, classs / padrões de alto nível, ShairedPreferences, etc.).

    Pessoalmente, tive muitos problemas ao manter uma instância de fragment (normalmente ao recriair ou reativair fragments através de mudanças de configuration ou sair e voltair a entrair no aplicativo), resultando geralmente em dois fragments, um deles conectado a vistas, apátrida, portanto inútil; e o "real" que mantém o estado anterior sem qualquer connection às visualizações, resultando em exceções e todo tipo de facilidade que você não quer ter.

    Comece por não reter a instância e veja o que apairece.

    Você poderia usair mHandler.removeCallbacksAndMessages (null) em muitas situações paira mim.

    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.