使用FragmentStatePagerAdapter时如何刷新片段视图

9

看起来刷新问题以前已经讨论过,但是没有一个解决方案对我奏效。

我的目标: 我正在使用FragmentStatePagerAdapter。适配器的每个位置都包含一个具有象棋格子外观的线性布局,其中每个单元格由CheckedTextView表示。

此外,我希望设置一个监听器用于监听单元格的点击事件,并删除先前选择的单元格并进行新选择。

已完成的工作: 每个片段都已正确加载,并显示出所有数据/默认状态(在列表中加载片段时计算)。

当我单击一个单元格时,保存的单元格列表中的所有状态都被正确获取,同时我还可以在调试代码时查看状态更改。同时,我为表示单元格的CheckedTextView分配了一个新状态,如下所示:

CheckedTextView cellView = (CheckedTextView) GridRow.getChildAt(c);
                                cellView.setSelected(false);
                                cellView.setChecked(false);
                                cellView.setTag(cellsChess.get(i).get(c));
问题: 尽管数值被正确地存储和分配,但视图不能被刷新,视图中的单元格数值没有得到更新。 我尝试过但没用的技巧: 1. 调用adapter.notifyDataSetChanged: 只有在我们重写了FragmentStatePagerAdapter时才能在使用时调用。
@Override
    public int getItemPosition(Object object){
        return POSITION_NONE;
    }

2. 添加覆盖DestroyItem方法并将片段添加到getItem的Map上:

这不适合我正在使用FragmentStatePagerAdapter,因此使用此pagerAdapter的整个目的将会消失。

3. 调用invalidate: 在此情况下不适用,我需要实时刷新。

4. 在instantiateItem()中使用setTag()方法: 我认为在这种情况下不适用。

参考线程: 在恢复活动时刷新FragmentStatePagerAdapter上的图像

ViewPager PagerAdapter未更新视图

动态更新ViewPager?

notifyDataSetChanged无法更新ListView

我已尽力清晰地表述了我的问题,如果有人需要更多澄清,请询问。

高度赞赏紧急回复,

干杯

****更新*****

我正在使用ViewPagerIndicator,而不是默认的ViewPager。


选择功能对于所有片段都是相同的(没有具体细节)。而且我也不打算从视图页更新任何内容,一切都在片段中。很抱歉,保密协议不允许我分享代码。简而言之,我如何在片段监听器中更新视图。谢谢。 - AliR
FragmentAdapter中的Fragment通常是自包含的 - 除非Fragment在其自身上更改视图,否则您无法做太多事情,除非使用像WeakReference MapfindViewByTag这样的黑客技巧。如果您需要从Activity中执行此操作并且不喜欢使用黑客技巧,您需要建立自己的Activity -> Fragment通信方式,而不依赖于Activity能够获取对Fragment的引用(例如广播,Guava的事件总线 - 或者Otto - 或Ambassador等)。就个人而言,我选择了WeakReference Map - 它比清晰的方法简单得多。 - Delyan
你的代码中是否使用了一些适配器-GridView组合或者GridRow只是像LinearLayout这样的布局?如果是GridView,请考虑更新数据并调用myGridAdapter.notifyDataSetChanged();,但我猜你没有使用GridView。在这种情况下,请尝试调用GridRow.requestLayout();如果你正在从Fragment的代码中更新Fragment的GUI,则不应该需要所有这些,可能有其他问题。尝试制作一个pager、一个cell fragment并分享你的代码。 - M-Wajeeh
好的谢谢各位,请让我检查一下,就像@M-WaJeEh所说的那样,我会回复您相关的代码。是的,我没有使用GridView,实际上只有LinearLayout,而GridRow只是一个CheckedTextView的行。同时,在Fragment的代码中也更新了我的片段。 - AliR
更新:已经开始处理应用程序的其余部分,但尚未找到解决方案。 - AliR
显示剩余6条评论
1个回答

0
关于 notifyDataSetChanged() 方法,我有两种不同的经验。
当我使用我的 ArrayAdapter 的子类来更新一个 ListView 时,它工作得很顺利。当我调用 notifyDataSetChanged() 时,ListView 中的项目会被更新。
然而,当我使用 FragmentStatePagerAdapter 的子类来更新 ViewPager 时,调用 notifyDataSetChanged() 却不能起作用。NotifyDataSetChanged() 负责调用所有已注册 DataSetObserver 的 onChanged() 函数,但观察者没有像在 ArrayAdapter 中那样自动注册。你必须自己做基础工作。
令我惊讶的是,DataSetObserver 不是一个接口,而是一个抽象类。所以我不能简单地在我的 fragment 子类中实现它。我必须定义一个 DataSetObserver 的子类,然后在这个类中定义一个成员字段作为对我的 fragment 的引用,在覆盖的 onChanged() 函数中更新你的 View 显示。代码如下:
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();
}
}

你必须小心谨慎。在你重写的fragment.onDestroy()方法中,记得将引用设置为null并注销DataSetObserver对象,否则该片段无法被垃圾回收。

后来,通过查看源代码,我发现ArrayAdapter和FragmentStatePagerAdapter不是兄弟关系,它们完全不同。它们实际上来自不同的包:

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

这就是为什么前者很容易工作而后者却不行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接