justinrixx
justinrixx

Reputation: 801

Update ListView in Viewpager

Forgive my ignorance of Android. I'm just learning. I'm building an app that uses Google's SlidingTabsColors sample code for the main layout (The developer website) .

I've got the layout working the way I want it to with dummy data. The idea is each tab will store a user's score for each round and then display their total score so far at the bottom.

Screenshot

Knowing what's where is helpful. The ListView and TextView are in the ViewPager, the Button at the bottom is part of the fragment containing the tabs and the ViewPager. Currently, when the button is pressed, a new entry is added to each player's data set (an ArrayList<Integer>') with the value of 0`. The user can then tap an item and edit it.

That's what works. But the ListView doesn't update unless it's told to. So when you click the button, there is no change to the UI until you swipe to the next item and the fragment is refreshed. So everything is being added correctly, I just don't know how to tell the current ListView to update.

Here's the code for the addRound() method in the parent fragment:

public void addRound() {
    // add a blank round for each player in their dataset
    for (int i = 0; i < mData.size(); i++) {
        mData.get(i).second.add(0);
    }

    // get the pager adapter
    DefaultGameFragmentPagerAdapter adapter = (DefaultGameFragmentPagerAdapter) mViewPager.getAdapter();
    
    int pos = mViewPager.getCurrentItem();
    ContentFragment frag = (ContentFragment) adapter.getItem(pos);
    if (frag != null) {
        frag.update();
    }
}

And the update() method in ContentFragment:

public void update() {
    mAdapter.notifyDataSetChanged();
}

I get a NullPointerException when I try to access my custom ArrayAdapter, but if I'm getting the current fragment from the ViewPager, shouldn't all those members be initialized? (The ListView is set up in the onViewCreated() method)

Thanks for taking the time to read!

Justin

Upvotes: 0

Views: 900

Answers (2)

serkanozel
serkanozel

Reputation: 2927

Okay Justinrixx, let's try few things:

First, let's create a public method in your Fragment which returns the instance of your ArrayAdapter e.g getScoreAdapter().

Second, let's create a public method in your custom ArrayAdapter to (re)set the dataset e.g. setDataset(ArrayList<int> playerScores);

Now in your addRound() method, after you ensure the frag isn't null, get the instance of your adapter via getScoreAdapter(), then, on that instance, set adapter's new data set via setDataset() and by proving the new data set. And last, call adapter's notifyDataSetChanged() method.

Goes without saying, your custom ArrayAdapter should hold an instance of the dataset it uses, either passed in constructor or set with our new method setDataset() method.

The reason of my suggestion was due to what I see or don't see in your code; in other words, I couldn't see reliably how your adapter received the changed dataset; hence my suggestion of clearly setting new datasets to adapters, making sure adapters keep using the new set dataset and finally notifying them of the change. Hope this helps.

Upvotes: 1

Abhishek V
Abhishek V

Reputation: 12526

ContentFragment frag = (ContentFragment) adapter.getItem(pos);

Never use getItem() function of the adapter to get the current fragment from ViewPager. It is called internally to instantiate the fragment and we are not supposed to call it explicitly. The Fragment returned by calling getItem is not the actual fragment present in ViewPager at that position. So update call doesn't update the data in intended fragment.

Try using one of the methods discussed in this link.

Upvotes: 1

Related Questions