当适配器更改时,FragmentTabHost中的List Fragment不会更新

时间:2013-09-16 12:01:03

标签: android android-fragments android-listfragment fragment-tab-host

我有一个包含片段的FragmentActivity。 这个片段包含一个FragmentTabHost。 选项卡主机包含三个选项卡,每个选项卡都是一个ListFragment。

列表配置了自定义适配器,可从主FragmentActivity获取更新,并在更新时调用notifyDatasetChanged。

我的问题是,ListFragment UI似乎永远不会在显示时更新视图。 如果我更改标签 - 我可以看到列表更新,但是当屏幕上显示列表时,我无法实时看到更新。

这是包含FragmentTabHost的片段的定义:

public class SubOptionFragmentManager extends Fragment 
{
    FragmentTabHost mTabHost;
    SoiListFragment mFrag1;
    SoiListFragment mFrag2;
    SoiListFragment mFrag3;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    {
        return inflater.inflate(R.layout.soi_container, container, false);
    }

    public void init(FragmentManager fm, int optionInstanceID) 
    {
        mOptionInstanceID = optionInstanceID;

        // find and setup the tabhost
        mTabHost = (FragmentTabHost)getActivity().findViewById(android.R.id.tabhost);
        mTabHost.setup(getActivity(), getChildFragmentManager(), R.id.realtabcontent);

        // add the three tabs
        mTabHost.addTab(mTabHost.newTabSpec("1")
                        .setIndicator("1"),
                        SoiListFragment.class,
                        getTabBundle("1", optionInstanceID));

        mTabHost.addTab(mTabHost.newTabSpec(dsTag)
                .setIndicator("2"),
                SoiListFragment.class,
                getTabBundle("2", optionInstanceID));

        mTabHost.addTab(mTabHost.newTabSpec("3")
                .setIndicator("3"),
                SoiListFragment.class,
                getTabBundle("3", optionInstanceID));

        // get reference to the fragments added
        mFrag1 = (SoiListFragment)getChildFragmentManager().findFragmentByTag("1");
        mFrag2 = (SoiListFragment)getChildFragmentManager().findFragmentByTag("2");
        mFrag3 = (SoiListFragment)getChildFragmentManager().findFragmentByTag("3");
    }

    public void HandleSoiItemUpdate(SubOptionInstanceItem soi, int fragID)
    {
        Log.i(TAG, "ItemUpdate:" + soi.toString());
        updateItemRunnable ur = new updateItemRunnable(soi, int fragID);

        getActivity().runOnUiThread(ur);
    }

    class updateItemRunnable implements Runnable
    {
        SubOptionInstanceItem mItem;
        int mFragID;

        public updateItemRunnable (SubOptionInstanceItem item, int fragID)
        {
            mItem = item;
        }

        public void run() 
        {
            switch (mFragID)
            {
                // the second parameter - true means it calls notifyDatasetChanged() after updating the item
                case 1:
                    mFrag1.getAdapter().updateItem(mItem, true);
                break;
                case 2:
                    mFrag2.getAdapter().updateItem(mItem, true);
                break;
                case 3:
                    mFrag3.getAdapter().updateItem(mItem, true);
                break;
            }
        }
    }
}

该类中还包含ListFragment对象:

public static class SoiListFragment extends ListFragment
    {
        private int mOptionInstanceID; 
        private int mPageType;


        @Override
        public void onCreate(Bundle savedInstanceState) 
        {
            super.onCreate(savedInstanceState);

            mOptionInstanceID = getArguments().getInt(FIELD_OPTION_INSTANCE_ID);
            mPageType = getArguments().getInt(FIELD_PAGE_TYPE);
        }

        public SubOptionInstanceAdapter getAdapter() 
        {
            return (SubOptionInstanceAdapter)getListAdapter();
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
        {
            // inflate the list view and return it
            View v = inflater.inflate(R.layout.soi_list, container, false);

            init();

            return v;
        }

        public void init()
        {
            SubOptionInstanceAdapter mAdapter = null;

            switch(mPageType)
            {
                case 1:
                    mAdapter = new SubOptionInstanceAdapter(getActivity(), 
                                                            R.layout.soi_item, 
                                                            Globals.getList1());
                break;
                case 2:
                    mAdapter = new SubOptionInstanceAdapter(getActivity(), 
                                                            R.layout.soi_item, 
                                                            Globals.getList2());
                break;
                case 3:
                    mAdapter = new SubOptionInstanceAdapter(getActivity(), R.layout.soi_item, Globals.getList3());
                break;
            }

            setListAdapter(mAdapter);
        }

片段布局“soi_container.xml”(包含FragmentTabHost的简单布局):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@color/background" >

    <android.support.v4.app.FragmentTabHost
        android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="0" />

    </android.support.v4.app.FragmentTabHost>

    <FrameLayout
        android:id="@+id/realtabcontent"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

</LinearLayout>

1 个答案:

答案 0 :(得分:0)

我的第一个问题是init()部分的onCreateView展示位置。 这导致每次加载或更改选项卡时都会发生init() - 这就是为什么我认为只有在不可见时才更新选项卡。

此外,在容器中的init()上获取ListFragments引用是错误的,因为在该点上尚未创建片段。

最后我的解决方案是在OnStart事件期间在容器片段上创建选项卡,获取列表片段引用并在onTabCreated事件中使用适配器初始化它们,然后使用我得到的引用更新它们之前。

编辑: Ravi的代码示例 - 获取列表片段参考

public void onTabCreated(int pageType)
{
    // if I don't already have the reference for the fragment
    if (mFrag1 == null)
    {
        mFrag1 = (SoiListFragment)getFragmentManager().findFragmentByTag("1");
    }
}