9

Seems the refresh issue is discussed before, but none of the solutions worked for me.

What I am trying to do: I am using FragmentStatePagerAdapter. Each position of the adapter holds a fragment that has a linear layout that has chess like appearance, with each cell represented by a CheckedTextView.

And a listener that should listens for clicks and removes the previous selection on the cells and makes the new selection.

Whats working: Each fragment is loaded correctly with all the data/default states (calculated while the fragment is loaded in a list)

When I click a cell all the states from the saved cells list are fetched correctly and I can change see the state change in the code while debugging. At the same time I assign a new state for the CheckedTextView which represent a cell. This is set like:

CheckedTextView cellView = (CheckedTextView) GridRow.getChildAt(c);
                                cellView.setSelected(false);
                                cellView.setChecked(false);
                                cellView.setTag(cellsChess.get(i).get(c));

The Issue: Even though the values are stored and assigned correctly the view can't be refreshed the values of the cells in the view do not get updated.

Tips I have Tried that didn't worked: 1. Call adapter.notifyDataSetChanged: Can be called while using FragmentStatePagerAdapter only when we have overridden:

@Override
    public int getItemPosition(Object object){
        return POSITION_NONE;
    }

2. Adding Overriden methods for DestroyItem and also adding the fragments to a Map on getItem:

This is not appropriate as I am working with FragmentStatePagerAdapter, so the whole purpose of using this pagerAdapter would be gone.

3. Calling invalidate: This is inappropriate for this scenario, I need realtime refresh.

4. setTag() method in instantiateItem(): I don't think this is appropriate in this situation.

Referenced threads: Refresh images on FragmentStatePagerAdapter on resuming activity

ViewPager PagerAdapter not updating the View

Update ViewPager dynamically?

notifyDataSetChanged fails to update ListView

I have tried to state my issue as clear as possible, if anyone needs more clarification, do ask.

Urgent replies will be highly appreciated,

Cheers

****Update*****

I am using the ViewPagerIndicator, instead of the default ViewPager.

Community
  • 1
  • 1
AliR
  • 2,065
  • 1
  • 27
  • 37
  • in your setup, what does each fragment represent? Is it only one fragment showing on the screen at a time? Where is the code you added? Is it inside the fragment class? Finally, what is GridRow? – Sherif elKhatib Mar 04 '13 at 09:48
  • Hi Sherif, each fragment represent a chess board. I have an activity which calls a container fragment, this containerFragment has a viewpager which has the FragmentStatePagerAadaper set. Each adapter item is a fragment and in this fragment in its onCreatView each chess view is initialised. Also the listener for a cell is in the same fragment where I check for current states and new state and change the state accordingly. A GridRow is just a row of checkedTextview representing a cell. I hope this answers all your questions, any hints....? – AliR Mar 05 '13 at 00:35
  • The fact that everything happens inside your fragment means that all this hassle is not needed. Are you sure your selector (background) is correct? Can you show it and your xml for each cell. Usually the case when the view is not updating happens when you're trying to update a specific fragment inside the viewpager. – Sherif elKhatib Mar 05 '13 at 08:59
  • The selection functionality is same for all fragments (no specifics). And also I am not trying to update anything from the view pager, its all in the fragment. Sorry the NDA doesn't allow me to share code. In short, how can I update the view within the fragment listener. Thanks – AliR Mar 05 '13 at 22:47
  • `Fragment`s in `FragmentAdapter`s are generally self-contained - unless the `Fragment` changes its views on its own, you really can't do much about it without hacks like a `WeakReference` `Map` and `findViewByTag`. If you need to do it from the `Activity` and abhor the hacks, you need to establish your own way to do `Activity` -> `Fragment` communication that doesn't rely on the `Activity` being able to get a reference to the `Fragment` (e.g., broadcasts, event buses like Guava's - or Otto - or Ambassador, etc.). Personally, I choose the WeakReference Map - it's far simpler than the clean way. – Delyan Mar 06 '13 at 15:52
  • Thanks @Delyan for the input, yes the Fragment changes its views on its own. Doing it from the Activity makes no sense here. Its just about refresh/update of the fragment view on changes made within the fragment. – AliR Mar 06 '13 at 23:02
  • Are you using some adapter-`GridView` combination in your code or `GridRow` is just some layout like `LinearLayout`, if it is a `GridView` then consider updating your data and calling `myGridAdapter.notifyDataSetChanged();` but I guess you are not using `GridView`. In that case try calling `GridRow.requestLayout();` If you are updating your `Fragment`s GUI from `Fragment`'s code then you shouldn't be needing all this, something else is wrong. Try making one pager, one cell fragment and share your code. – M-Wajeeh Mar 09 '13 at 02:28
  • I think it will be easy by just resetting/reinitializing the `FragmentStatePagerAdapter`. If it does not work then Please post your code so that I can serve you better... – Aashutosh Sharma Mar 10 '13 at 02:28
  • ok thanks guys let me check and will get back with the relevant code like @M-WaJeEh says. And yes I am not using GridView, its actually only LinearLayout, and GridRow is just a row of checkedTextview. And yes also that I am updating my fragment within Fragment's code – AliR Mar 10 '13 at 22:49
  • Update: started work on rest of the app, haven't found a solution yet. – AliR Mar 21 '13 at 01:39
  • @AliR did you ever found a solution for this? Can you post the correct answer? – iamgopal Aug 02 '20 at 08:34

1 Answers1

0

In relation to notifyDataSetChanged() function, I have two different experiences.

When I used my subclass of ArrayAdapter to update a ListView, it worked straight. When I called notifyDataSetChanged(), the ListView items are updated.

However, when I used a subclass of FragmentStatePagerAdapter to update a ViewPager, calling notifyDataSetChanged() did not work. NotifyDataSetChanged() is responsible for calling the onChanged() function of all registered DataSetObserver, but the observers have not been registered automatically like in ArrayAdapter. You have to do the ground work by yourself.

To my surprise, DataSetObserver is not a interface but an abstract class. So I could not simply implement it in my subclass of fragment. I have to define a subclass of DataSetObserver, then define a member field in this class as a reference to my fragment, and in the overriden onChanged() function update your View display. The code is as follows:

public class DetailFragDataSetObserver extends DataSetObserver {
private DetailTextFragment view_instance;
protected static ArrayList<DetailFragDataSetObserver> list = new ArrayList<DetailFragDataSetObserver>();

public DetailFragDataSetObserver(DetailTextFragment f){
    view_instance = f;
    list.add(this);
}
public DetailTextFragment getView(){
    return view_instance;
}
public static DataSetObserver findDataSetObserverFor(DetailTextFragment f){
    for ( int i = 0; i<list.size(); i++){
        if ( list.get(i).getView() == f)
            return list.get(i);
    }
    return null;
}
public static void release(DataSetObserver observer){
    list.remove(observer);
    ((DetailFragDataSetObserver)observer).view_instance = null;
}
@Override
public void onChanged(){
    assert null != view_instance;

    view_instance.vUpdateData();
}
}

You have to be careful. You need to remember to nullify the reference and unregister the DataSetObserver object in your overriden fragment.onDestroy(), otherwise the fragment cannot be garbage collected.

Later, through looking into the source codes, I found ArrayAdapter and FragmentStatePagerAdapter and are not siblings. They are totally different. They are actually from different packages:

  android.widget.ArrayAdapter
  android.support.v4.app.FragmentStatePagerAdapter

That's why the former worked easily while the latter does not.

gm2008
  • 4,245
  • 1
  • 36
  • 38