Question

I'm trying to make a ListFragment that will periodically be updated (Calls to update not shown here, but the update function is). Here's the log cat that I'm seeing:

04-05 11:05:44.252: V/QslLogFrag(2690): onCreate()
04-05 11:05:44.256: V/QslLogFrag(2690): onCreateView()
04-05 11:05:44.304: V/QslLogFrag(2690): onActivityCreate()
04-05 11:05:44.612: V/QslLogFrag(2690): null
04-05 11:05:44.736: V/QslLogFrag(2690): com.kd7uiy.qslmapper.QslLogAdapter@5282f55c
04-05 11:05:47.948: V/QslLogFrag(2690): null

The last 3 lines lines are all provided in the updateView class, which is called externally when there's new data to check. The first two are called essentially automatically, the third one is called by user input.

And the code:

public class QslLogFragment extends ListFragment {

    private CursorAdapter mAdapter;

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        getListView().setFastScrollEnabled(true);
        Cursor cursor = QslDatabase.getInstance(getActivity()).getTableQuery(
                mFilters);
        mAdapter= new QslLogAdapter(getActivity(), cursor, 0);
        setListAdapter(mAdapter);
        Log.v(TAG,"onActivityCreate()");
    }

    public void updateView() {
        Cursor cursor = QslDatabase.getInstance(getActivity()).getTableQuery(
                mFilters);
        Log.v(TAG,""+getListAdapter());
        if (getListAdapter() != null) {
            ((CursorAdapter) getListAdapter()).changeCursor(cursor);
        }
    }

Somehow it seems to me as if the adapter is getting set to null. Note I can still scroll through the ListView without problems, but I can't update it, with a new set of filters. Any ideas what's happening?

Note, QslAdapter extends CursorAdapter, and I'm using the Support Library CursorAdapter.

Here's a list of things I've tried:

  1. I have tried just using setListAdapter and getListAdapter.
  2. I have tried not using getListAdapter, but just keeping a reference to mAdapter.
  3. I have verified that there is only one instance of this Fragment.
  4. I am not calling setListAdapter anywhere.
  5. I've verified that getListAdapter and mAdapter always report the same pointer, or null.
Was it helpful?

Solution

If @commonsware doesn't mind, I'll put this into an answer for prosperity. Although I'm sure if he has any further insights, he will create a much better answer.


I had the feeling you could be dealing with multiple copies of your QslLogFragment. I have faced similar problems previously.

In situations like this, it is a good idea to log your method calls, like you have done. Where it is "impossible" for the adapter to be different, that is the hint of having 2 fragments, hence the suggestion to log the fragment as well.

Place extra logs in ALL the Activity & Fragment lifecycle methods to track down the final piece of the puzzle. It may seem like overkill, but you could find some surprises.


In the case that I had, which you reminded me of, I had based my code on an Android SDK sample that actually created a new fragment each time I tried to access it. I had not cached any of the fragments that were previously created. So check the code that retrieves (or creates) your fragment.

Here is the code from my FragmentPagerAdapter that creates a new fragment each time. This is bad code, and I don't recommend it, but for now it serves its purpose in the demo it comes from.

public Fragment getItem(int position)
{
    // TODO don't create a new fragment each time this is called
    switch (position)
    {
        case 0:
        {
            return new WindFragment();
        }
        // more cases... etc...
        default:
        {
            return new TemperatureFragment();
        }
    }
}

This is called every time the user flips to a new page, to show a different fragment. This code caused an issue very similar to yours.

OTHER TIPS

My issue was very close to Richard's answer, but I'll post a better version of the code.

I have been using a function called TabsAdapter to manage my FragementPager. The default code is this:

    @Override
    public Fragment getItem(int position) {
        TabInfo info = mTabs.get(position);
        return Fragment.instantiate(mContext, info.clss.getName(), info.args);
    }

I was setting a listener to the code by using the getItem function (My private listener), and thus was actually creating a new fragment!

The solution was to use a WeakHashMap to store previous instances of the fragment so I don't re-create them if I don't have to!

WeakHashMap<Integer,Fragment> mFragmentMap;

@Override
public Fragment getItem(int position) {
    TabInfo info = mTabs.get(position);
    if (mFragmentMap.get(position)==null){
        mFragmentMap.put(position,Fragment.instantiate(mContext, info.clss.getName(), info.args));
    }
    return mFragmentMap.get(position);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top