2017-01-05 2 views
0

J'ai trouvé plusieurs questions à ce sujet, aucune de ces réponses ne m'aide. Chaque question concerne d'autres fonctions et vues que je n'implémente pas dans mes fragments, et le problème n'est pas que j'ai besoin d'échanger ma méthode pour obtenir le FragmentManager à getChildFragmentManager() n'importe où dans mes fragments, parce que je n'ai pas besoin de FragmentManager là.Les adaptateurs FragmentTabHost Fragment sont vides lors du retour à l'onglet, les fragments/vues restent

Je suppose que mon problème provient des fragments et non du FragmentTabHost dans l'activité principale, mais je ne suis pas vraiment sûr. Du tout. Tout ce que je sais, c'est que lorsque vous faites la page entre les onglets, le contenu de l'adaptateur disparaît, mais pas le fragment lui-même. Toutes les vues sont toujours fonctionnelles, donc la fonctionnalité de chaque fragment reste intacte.

Ce problème a surgi seulement après avoir ajouté un écouteur de changement d'onglet pour quand initialiser l'adaptateur pour mon fragment de conversation.

Notez que le contenu des onglets est correct lors de leur initialisation initiale, mais lorsque vous revenez à l'onglet, le contenu des cartes est vide. Cela signifie que l'onglet qui n'a pas encore été initialisé lors de la création de FragmentTabHost, les onglets masqués n'ont pas encore été initialisés. Ils fonctionneront donc toujours la première fois que vous leur adresserez une page. Par le débogage, je peux voir que ce problème se produit lorsque la transition se produit, et toutes les cartes resteront vides pendant la durée de la session d'utilisation. Je mets cette snippit de code avant les contrôles initiaux dans mon appel tabHost.setOnTabChangedListener:

//Before paging back to an initialized tab for the first time, the adapters of the initialized tab is populated. 
Log.d("test", "pre"); 
new Handler().postDelayed(new Runnable() { 
    @Override 
    public void run() { 
     //At this point, the adapter is empty. 
     Log.d("test", "post"); 
    } 
}, 50); 

Les deux fragments sont les suivants:

public class GroupTasksFragment extends Fragment { 

public ArrayAdapter<String> adapter; 
private Context context; 
public ListView taskListView; 

public GroupTasksFragment() { 
    // Required empty public constructor 
} 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    View rootView = inflater.inflate(R.layout.fragment_group_tasks, container, false); 
    taskListView = (ListView) rootView.findViewById(R.id.tasksList); 
    adapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, new ArrayList<String>()); 
    taskListView.setAdapter(adapter); 
    return rootView; 
} 

@Override 
public void onAttach(Context context) { 
    super.onAttach(context); 
    this.context = context; 
} 

@Override 
public void onDetach() { 
    super.onDetach(); 
} 
} 

public class GroupChatFragment extends Fragment{ 

public ArrayAdapter<String> adapter; 
private Context context; 
public ListView chatListView; 

public GroupChatFragment() { 
    // Required empty public constructor 
} 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
         Bundle savedInstanceState) { 
    View rootView = inflater.inflate(R.layout.fragment_group_chat, container, false); 
    chatListView = (ListView) rootView.findViewById(R.id.chatList); 
    adapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, new ArrayList<String>()); 
    chatListView.setAdapter(adapter); 
    return rootView; 
} 

@Override 
public void onAttach(Context context) { 
    super.onAttach(context); 
    this.context = context; 
} 

@Override 
public void onDetach() { 
    super.onDetach(); 
} 
} 

L'activité principale avec le FragmentTabHost (j'exclus des méthodes il suffit de prendre l'entrée et envoyer du contenu à PubNub):

public class GroupContentActivity extends AppCompatActivity { 

private GroupChatFragment chatFrag; 
private GroupTasksFragment taskFrag; 
private FragmentTabHost tabHost; 
private PubNub connection; 
private String groupName; 
private String nickName; 
private boolean chatFragInitialized = false; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_group_content); 
    tabHost = (FragmentTabHost) findViewById(android.R.id.tabhost); 
    tabHost.setup(this, getSupportFragmentManager(), android.R.id.tabcontent); 

    tabHost.addTab(tabHost.newTabSpec("tasks").setIndicator("Tasks"), 
      GroupTasksFragment.class, null); 

    tabHost.addTab(tabHost.newTabSpec("chat") 
      .setIndicator("Chat"), GroupChatFragment.class, null); 

    groupName = getIntent().getStringExtra("groupName"); 
    nickName = getIntent().getStringExtra("nickName"); 
    PNConfiguration config = new PNConfiguration(); 
    config.setPublishKey(Constants.publishKey); 
    config.setSubscribeKey(Constants.subscribeKey); 
    connection = new PubNub(config); 



    tabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() { 
     @Override 
     public void onTabChanged(String tabId) { 
      if (!chatFragInitialized && tabId.equals("chat")) { 
       chatFragInitialized = true; 
       new Handler().postDelayed(new Runnable() { 
        @Override 
        public void run() { 
         chatFrag = (GroupChatFragment) getSupportFragmentManager().findFragmentByTag("chat"); 
         connection.history() 
           .channel(groupName) 
           .count(50) 
           .async(new PNCallback<PNHistoryResult>() { 
            @Override 
            public void onResponse(PNHistoryResult result, PNStatus status) { 
             for (PNHistoryItemResult item : result.getMessages()) { 
              final String[] sForm = item.getEntry().getAsString().split(">>>>"); 
              String m = ""; 
              if (sForm.length > 2) { 
               for (int x = 1; x < sForm.length; x++) { 
                m += sForm[x]; 
               } 
              } else { 
               m = sForm[1]; 
              } 

              final String mCopy = m; 

              runOnUiThread(new Runnable() { 
               @Override 
               public void run() { 
                switch (sForm[0]) { 
                 case "groupCreated": 
                  chatFrag.adapter.clear(); 
                  break; 
                 case "chat": 
                  chatFrag.adapter.add(mCopy); 
                } 
               } 
              }); 

             } 
            } 
           }); 
        } 
       }, 50); 
      } 
     } 
    }); 

    new Handler().postDelayed(new Runnable() { 
     @Override 
     public void run() { 
      taskFrag = (GroupTasksFragment) getSupportFragmentManager().findFragmentByTag("tasks"); 

      connection.history() 
        .channel(groupName) 
        .count(50) 
        .async(new PNCallback<PNHistoryResult>() { 
         @Override 
         public void onResponse(PNHistoryResult result, PNStatus status) { 
          for (PNHistoryItemResult item : result.getMessages()) { 
           final String[] sForm = item.getEntry().getAsString().split(">>>>"); 
           String m = ""; 
           if (sForm.length > 2) { 
            for (int x = 1; x < sForm.length; x++) { 
             m += sForm[x]; 
            } 
           } else { 
            m = sForm[1]; 
           } 

           final String mCopy = m; 

           runOnUiThread(new Runnable() { 
            @Override 
            public void run() { 
             switch (sForm[0]) { 
              case "addTask": 
               if (taskFrag.adapter.getPosition(mCopy) < 0) { 
                taskFrag.adapter.add(mCopy); 
               } 
               break; 
              case "deleteTask": 
               if (taskFrag.adapter.getPosition(mCopy) >= 0) { 
                taskFrag.adapter.remove(mCopy); 
               } 
               break; 
              case "groupCreated": 
               taskFrag.adapter.clear(); 
               break; 
             } 
            } 
           }); 

          } 
         } 
        }); 

      connection.addListener(new SubscribeCallback() { 
       @Override 
       public void status(PubNub pubnub, PNStatus status) { 
        if (status.getCategory() == PNStatusCategory.PNUnexpectedDisconnectCategory) { 
         Toast.makeText(getApplicationContext(), "You were disconnected!", Toast.LENGTH_SHORT).show(); 
        } else if (status.getCategory() == PNStatusCategory.PNConnectedCategory) { 
         if (status.getCategory() == PNStatusCategory.PNConnectedCategory) { 
          pubnub.publish().channel(groupName).message("chat>>>><ADMIN> User '" + nickName + "' Connected").async(new PNCallback<PNPublishResult>() { 
           @Override 
           public void onResponse(PNPublishResult result, PNStatus status) { 
           } 
          }); 
         } 
        } else if (status.getCategory() == PNStatusCategory.PNReconnectedCategory) { 
         Toast.makeText(getApplicationContext(), "You were reconnected!", Toast.LENGTH_SHORT).show(); 
        } 
       } 

       @Override 
       public void message(PubNub pubnub, PNMessageResult message) { 
        final String[] sForm = message.getMessage().getAsString().split(">>>>"); 
        String m = ""; 
        if (sForm.length > 2) { 
         for (int x = 1; x < sForm.length; x++) { 
          m += sForm[x]; 
         } 
        } else { 
         m = sForm[1]; 
        } 

        final String mCopy = m; 

        runOnUiThread(new Runnable() { 
         @Override 
         public void run() { 
          switch (sForm[0]) { 
           case "chat": 
            if (chatFragInitialized) { 
             chatFrag.adapter.add(mCopy); 
             runOnUiThread(new Runnable() { 
              @Override 
              public void run() { 
               chatFrag.chatListView.setSelection(chatFrag.adapter.getCount() - 1); 
              } 
             }); 
            } 
            break; 
           case "addTask": 
            taskFrag.adapter.add(mCopy); 
            connection.publish().channel(groupName).message("chat>>>><ADMIN> Task '" + mCopy + "' added.").async(new PNCallback<PNPublishResult>() { 
             @Override 
             public void onResponse(PNPublishResult pnPublishResult, PNStatus pnStatus) { 
             } 
            }); 
            break; 
           case "deleteTask": 
            taskFrag.adapter.remove(mCopy); 
            connection.publish().channel(groupName).message("chat>>>><ADMIN> Task '" + mCopy + "' deleted.").async(new PNCallback<PNPublishResult>() { 
             @Override 
             public void onResponse(PNPublishResult pnPublishResult, PNStatus pnStatus) { 
             } 
            }); 
            break; 
          } 
         } 
        }); 
       } 

       @Override 
       public void presence(PubNub pubnub, PNPresenceEventResult presence) { 
       } 
      }); 
      connection.subscribe().channels(java.util.Collections.singletonList(groupName)).execute(); 
     } 
    }, 100); 
} 

@Override 
public void onDestroy(){ 
    super.onDestroy(); 
    connection.publish().channel(groupName).message("chat>>>><ADMIN> User '" + nickName + "' Logged Out.").async(new PNCallback<PNPublishResult>() { 
     @Override 
     public void onResponse(PNPublishResult pnPublishResult, PNStatus pnStatus) { 
     } 
    }); 
    connection.disconnect(); 
    Toast.makeText(getApplicationContext(), "Logged out", Toast.LENGTH_SHORT).show(); 
} 

//More Methods 
} 

Notez également que la question n'est pas que je dois stocker l'instance FragmentManager, comme cela ne veut pas faire n'importe quoi.

Répondre

0

J'ai trouvé mon problème. Il s'avère que chaque fois qu'un fragment est paginé dans le FragmentTabHost, sa méthode createView est appelée à nouveau, et seulement cette méthode, donc en paramétrant l'adaptateur dans le fragment à vider dans cette vue, ce que je pensais être seulement au début, Je réinitialise l'adaptateur à chaque fois.

J'ai corrigé ce problème en conservant le contenu de l'adaptateur en tant qu'objet de liste de variables d'instance que j'ajoute ou supprime des chaînes lorsque je souhaite changer d'adaptateur. NE METTEZ PAS AUSSI LES CORDES DANS L'ADAPTATEUR, la mise à jour de la liste suffit. La liste l'ajoutera directement à l'adaptateur.

Notez également que si vous définissez le contenu initial en dehors du fragment, il se peut qu'il ne s'affiche pas lorsque les onglets sont initialisés pour la première fois. Faites juste attention à votre ordre de déclaration et quand les choses sont appelées. La construction de fragments est une affaire géniale.

Ensuite, je définis l'adaptateur à tout ce qui est dans la liste chaque fois que la méthode createView est appelée.