3

私はActionBarSherlock の例を使用して構築しています。各タブに 1 つずつ、3 つのフラグメント(それぞれ extendsSherlockListFragmentと implement ) があります。それらはすべてローダーを使用します。タブ 2 と 3 は同じローダー クラスを使用しています (これは問題ではないと思います)。LoaderManager.LoaderCallbacks<>

FragmentPagerAdapter必要に応じてバンドルとともに、さまざまなフラグメントへのクラス参照を使用して、タブを my に追加します。アプリケーションが起動してタブ 0 が表示されると、 getItem のFragmentPagerAdapterタブ 0 とタブ 1 がフラグメントを作成して準備が整います。タブ 2 はまだ作成されていません。タブ 1 にスワイプすると、タブ 2 が読み込まれます。もう一度スワイプすると、タブ 2 が正しく表示されます。

タブ 0 からタブ 2 をクリックすると問題が発生しますgetItemフラグメントを作成し、ローダーがdoInBackground処理を開始しますが、タブ 2 のフラグメントはonLoadFinished でデータを取得しないため、無期限のプログレスバーが表示されたままになります。

奇妙なことが以前に起こりました。クリックすると、タブ 2onLoadFinishedがタブ 0 のローダーからデータを受け取ります。各タブのフラグメント ローダーを別の ID を使用するように変更すると (同じ ID であっても衝突する必要はないと思います)、その問題はなくなりました。例: getLoaderManager().initLoader(0, null, this)getLoaderManager().initLoader(1, null, this)など。それがローダーやその他のことについての私の無知を示​​しているだけなのかどうかはわかりません。

主な質問は、 にFragmentPagerAdapterすべてのタブを一度にロードさせることはできますか? それを行っても、おそらく私のコードでこのバグを完全に排除することはできません。

二次的な質問:スワイプして更新をクリックすると(それが何をするかについては以下のコードを参照)、最終的にアクションバーの更新ボタンが消えます。何かご意見は?

MainActivity (リンクされた ABS の例と非常によく似ています):

public class MainActivity extends SherlockFragmentActivity{

    private static final int NUMBER_OF_STREAMS = 9;

    ViewPager mViewPager;
    TabHost mTabHost;
    TabsAdapter mTabsAdapter;
    private JTVApplication mApplication;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Set up application
        if (mApplication == null)
            this.mApplication = (JTVApplication)getApplication();

        mTabHost = (TabHost)findViewById(android.R.id.tabhost);
        mTabHost.setup();

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.pager);

        // SET UP TABS ADAPTER
        mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager);     
        mTabsAdapter.addTab(mTabHost.newTabSpec("categories").setIndicator("Categories"), CategoryListFragment.class, null);
        mTabsAdapter.addTab(mTabHost.newTabSpec("top_streams").setIndicator("Top Streams"), StreamListFragment.class, StreamListFragment.instanceBundle(null, null, null, null, NUMBER_OF_STREAMS, 0));
        mTabsAdapter.addTab(mTabHost.newTabSpec("favorites").setIndicator("Favorites"), FavoriteListFragment.class, null);

        if (savedInstanceState != null) {
            mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab"));
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("tab", mTabHost.getCurrentTabTag());
    }
    /**
     * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
     * one of the sections/tabs/pages.
     */
    public static class TabsAdapter extends FragmentPagerAdapter implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {

        private final Context mContext;
        private final TabHost mTabHost;
        private final ViewPager mViewPager;
        private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();

        static final class TabInfo {
            @SuppressWarnings("unused")
            private final String tag;
            private final Class<?> clss;
            private final Bundle args;

            TabInfo(String _tag, Class<?> _class, Bundle _args) {
                tag = _tag;
                clss = _class;
                args = _args;
            }
        }

        static class DummyTabFactory implements TabHost.TabContentFactory {
            private final Context mContext;

            public DummyTabFactory(Context context) {
                mContext = context;
            }

            @Override
            public View createTabContent(String tag) {
                View v = new View(mContext);
                v.setMinimumWidth(0);
                v.setMinimumHeight(0);
                return v;
            }
        }


        List<Fragment> fragments = new ArrayList<Fragment>();

        public TabsAdapter(FragmentActivity activity, TabHost tabHost, ViewPager pager) {
            super(activity.getSupportFragmentManager());
            mContext = activity;
            mTabHost = tabHost;
            mViewPager = pager;
            mTabHost.setOnTabChangedListener(this);
            mViewPager.setAdapter(this);
            mViewPager.setOnPageChangeListener(this);   
        }

        public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
            tabSpec.setContent(new DummyTabFactory(mContext));
            String tag = tabSpec.getTag();

            TabInfo info = new TabInfo(tag, clss, args);
            mTabs.add(info);
            mTabHost.addTab(tabSpec);
            notifyDataSetChanged();
        }

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

        @Override
        public int getCount() {
            return mTabs.size();
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {}

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {}

        @Override
        public void onPageSelected(int position) {
            TabWidget widget = mTabHost.getTabWidget();
            int oldFocusability = widget.getDescendantFocusability();
            widget.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
            mTabHost.setCurrentTab(position);
            widget.setDescendantFocusability(oldFocusability);
        }

        @Override
        public void onTabChanged(String tabId) {
            int newPosition = mTabHost.getCurrentTab();
            mViewPager.setCurrentItem(newPosition, true);
        }


    }
}

Tab0 フラグメント (他のフラグメントと非常に似ているため、他のフラグメントは省略します):

public class CategoryListFragment extends SherlockListFragment implements LoaderManager.LoaderCallbacks<List<Category>>{

    public List<Category> mCategories;
    public List<Stream> mStreams;
    private int mLimit;
    private CategoryAdapter mCategoryAdapter;
    private String mSearchFilter;
    private RestClient mCategoryClient;

    public List<Category> getCategories() {
        return mCategories;
    }
    public void setCategories(List<Category> categories) {
        this.mCategories = categories;
    }

    public CategoryListFragment() {
    }

    @Override
    public void onCreate(Bundle savedInstance){
        super.onCreate(savedInstance);
        this.setHasOptionsMenu(true);

        if (mCategoryClient == null)
            this.mCategoryClient = JTVApi.getCategories();
        // Prepare the loader
        getLoaderManager().initLoader(0, null, this);
    }

    @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
        // CREATE REFRESH BUTTON
        MenuItem refreshMenu = menu.add("Refresh");
        refreshMenu.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
        refreshMenu.setIcon(R.drawable.ic_menu_refresh);
        refreshMenu.setOnMenuItemClickListener(new OnMenuItemClickListener() {
            public boolean onMenuItemClick(MenuItem item) {
                CategoryListFragment.this.setListShown(false);
                CategoryListFragment.this.getLoaderManager().restartLoader(0, null, CategoryListFragment.this);   
                return true;
            }
        });
    }


    @Override
    public void onLoadFinished(Loader<List<Category>> arg0, List<Category> data) {
        if (mCategories == null){
            mCategoryAdapter = new CategoryAdapter(getActivity(), R.id.listItem, data);
            this.setListAdapter(mCategoryAdapter);
        } else {
            mCategoryAdapter.setData(data);
        }
        this.setListShown(true);
    }
    @Override
    public void onLoaderReset(Loader<List<Category>> arg0) {
        // TODO check for null
        mCategoryAdapter.setData(null);
    }
    @Override
    public Loader<List<Category>> onCreateLoader(int arg0, Bundle arg1) {
        return new CategoryLoader(getActivity(), mLimit, mCategoryClient);
    }
}

Tab0 ローダー (他のローダーと非常によく似ているため、他のローダーは省略します):

public class CategoryLoader extends AsyncTaskLoader<List<Category>> {

    JTVApplication mApplication;
    RestClient mRestClient;
    List<Category> mCategories;

    public CategoryLoader(Context context, int limit, RestClient restClient) {
        super(context);
        this.mRestClient = restClient;
        mApplication = (JTVApplication)context.getApplicationContext();
    }

    @Override
    public List<Category> loadInBackground() {
        List<Category> categories = null;
        Object json;
        try {
            json = mApplication.getJSON(mRestClient, mRestClient.bypassCache());
            if (mRestClient.getApiMethod() == APIMethod.CATEGORY_LIST && json instanceof JSONObject){
                JSONObject jsonObject = (JSONObject)json;
                categories = Category.parseCategories(jsonObject);

                // Get total count of viewers for "All Categories"
                int total_viewers = 0;
                for (Category category : categories)
                    total_viewers += category.getViewers_count();
                categories.add(new Category(Category.ALL_CATEGORIES, "All Streams", total_viewers, 0, 0, null, "All Streams"));

                // Update global categories list with this data
                mApplication.setCategories(categories);

                return categories;
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Called when there is new data to deliver to the client.  The
     * super class will take care of delivering it; the implementation
     * here just adds a little more logic.
     */
    @Override
    public void deliverResult(List<Category> data) {
        mCategories = data;
        if (isStarted()) {
            super.deliverResult(data);
        }
    }

    /**
     * Handles a request to start the Loader.
     */
    @Override
    protected void onStartLoading() {
        if (mCategories != null){
            // If we currently have a result available, deliver it
            // immediately.
            deliverResult(mCategories);
        }

        // TODO CHECK FOR NEW DATA OR TIMER
        if (mCategories == null){
            forceLoad();
        }
    }

    /**
     * Handles a request to stop the Loader.
     */
    @Override protected void onStopLoading() {
        // Attempt to cancel the current load task if possible.
        cancelLoad();
    }

    /**
     * Handles a request to completely reset the Loader.
     */
    @Override
    protected void onReset() {
        super.onReset();
    }

}

アダプターは非常に基本的なものであり、問​​題はないと確信しています。誰かに尋ねられたら、もっとコードを提供できますが、これで十分だと思います。 助けてくれてありがとう。

アップデート:

単純に置き換えるFragmentPagerAdapterFragmentStatePagerAdapter機能します。FragmentPagerAdapter getItem is not calledで参照されているのを見ました。私のコードと使用の何が問題になっていますFragmentPagerAdapterか?

4

0 に答える 0