Фрагмент списка внутри FragmentTabHost не обновляется при изменении адаптера

У меня есть FragmentActivity, который содержит фрагмент. этот фрагмент содержит FragmentTabHost. Хост вкладок содержит три вкладки, каждая из которых является ListFragment.

Списки настроены с помощью настраиваемого адаптера, который получает обновления из основного FragmentActivity и вызывает notifyDatasetChanged при обновлении.

Моя проблема в том, что пользовательский интерфейс ListFragment никогда не обновляет представление, когда оно отображается. Если я переключаю вкладки - я вижу обновления списка, но не вижу обновлений в реальном времени, когда список отображается на экране.

Это определение фрагмента, содержащего 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>

person Shlomi    schedule 16.09.2013    source источник


Ответы (1)


Моей первой проблемой было размещение init() на части onCreateView. Это привело к тому, что init() возникало каждый раз, когда вкладка загружалась или изменялась, поэтому я думал, что вкладка обновляется только тогда, когда она не видна.

Кроме того, получение ссылки ListFragments на init() в контейнере было неверным, так как фрагменты еще не были созданы в этой точке.

Наконец, мое решение состояло в том, чтобы создать вкладки на фрагменте контейнера во время события OnStart, получить ссылку на фрагмент списка и инициализировать их с помощью адаптера в событии onTabCreated, а затем обновить их, используя ссылку, которую я получил ранее.

EDIT: пример кода для 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");
    }
}
person Shlomi    schedule 21.10.2013
comment
Можете ли вы опубликовать код, где вы получаете ссылку в onTabCreated, я немного застрял в получении ссылки на фрагменты - person Ravi; 21.11.2013