3

我正在使用ActionBarSherlock 示例进行构建。我有 3 个片段(每个扩展SherlockListFragment和实现LoaderManager.LoaderCallbacks<>),每个选项卡中有 1 个。他们都使用装载机。选项卡 2 和 3 使用相同的加载器类(我认为这不是问题)。

我将选项卡添加到我的选项卡中,FragmentPagerAdapter其中包含对不同片段的类引用,如果需要,还包括捆绑包。当我的应用程序启动并显示选项卡 0 时,getItem inFragmentPagerAdapter通过创建它们的片段来准备选项卡 0 和选项卡 1。选项卡 2 尚未创建。当我滑动到选项卡 1 时,会加载选项卡 2。当我再次滑动时,选项卡 2 正确显示。

当我从 tab 0 单击到 tab 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