FragmentTabHost Fragment Adapters Are Empty Upon Returning To Tab, Fragment/Views Remain

173 views Asked by At

I've found several questions about this, none of which help me. Each question relates to other functions and views I don't implement in my fragments, and the issue is not that I need to swap my method getting the FragmentManager to getChildFragmentManager() anywhere in my fragments, because I don't need to get a FragmentManager there.

I'm guessing that my issue stems from the fragments and not the FragmentTabHost in the main activity, but I am not really sure. At all. All I know is that when you page between tabs, the adapter content disappears, but not the fragment itself. All views are still functional, so the functionality of each fragment remains intact.

This issue popped up only after I added a tab change listener for when to initialize the adapter for my chat fragment.

Note that the content of the tabs is fine when they are first initialized, but when you return to the tab the content in the adapters empty. This means that the tab that is not initialized yet when the FragmentTabHost is created, the hidden tabs haven't been initialized yet, so they will still work the first time you page over to them.

Through debugging, I can see that this issue occurs when the transition happens, and all adapters will remain empty for the duration of the usage session. I put this snippit of code before the initial checks in my tabHost.setOnTabChangedListener call:

//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);

The two fragments are as follows:

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();
}
}

The main activity with the FragmentTabHost (I have excluded methods that just take input and send content to 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
}

Also note that the issue is not that I need to store the FragmentManager instance, as that doesn't do anything.

1

There are 1 answers

0
WondrousPiffle On BEST ANSWER

I found my issue. It turns out that every time a fragment is paged to in the FragmentTabHost, it's createView method is called again, and only that method, so by setting the adapter in the fragment to empty in that view, which I thought was only at the start, I reset the adapter each time.

I fixed this by keeping the adapter content as an instance variable list object that I add or remove strings to/from when I want to change the adapter. DO NOT ALSO PUT THE STRINGS IN THE ADAPTER, updating the list is enough. The list will directly add it to the adapter.

Also note that if you set the initial content outside of the fragment, it may not show when the tabs are first initialized. Just be careful of your statement ordering and when things are called. Fragment construction is funky business.

Then, I set the adapter to whatever is in the list each time the createView method is called.