8

我不熟悉FragmentPagerAdapter,所以这将是我们(你)批判性地阅读描述的问题之一。

结构:我有一个FragmentPagerAdapter(下面的代码),一次可以容纳两个片段。第一个显示书籍摘录,第二个显示书名列表。

目标:我想实现标题中描述的内容:用户可以导航到分页器中的第二个片段,单击一个标题,然后我想将用户移回第一个片段并告诉第一个片段进行更新文本。第一个片段有一个triggerRefresh方法。

代码:我相信我的问题是因为FragmentPagerAdapter重用/创建片段的方式(我不明白)。这是我的课:

static class MyFragmentPagerAdapter extends FragmentPagerAdapter {

    public MyFragmentPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        return NUM_ITEMS;
    }

    @Override
    public Fragment getItem(int position) {
        switch(position) {
        case 0:
            return new ExcerptsFragment();
        case 1:
            return new BookListFragment();
        default:
            throw new IllegalArgumentException("not this many fragments: " + position);
        }
    }
}

这就是我创建相关成员的方式:

ViewPager mViewPager = (ViewPager) findViewById(R.id.pager);
MyFragmentPagerAdapter mFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mFragmentPagerAdapter);

这就是我在我的活动中其他地方尝试过的,当我收到来自书名片段的回调并选择了标题时:

mViewPager.setCurrentItem(0); // back to excerpts screen page. It's OK.
// Here's the problem! How to identify the fragment 0 
// to ExcerptsFragment and call its triggerRefresh()?!?

系列问题:

调用适配器getView()将不起作用,因为它将返回 的新实例ExcerptsFragment,该实例不是当前附加的实例(如预期的那样,引发异常)。

我在这里看到很多人(示例)只是将片段存储在getView(). 那正确吗?因为通过查看官方示例,对我来说似乎是一种反模式(通过持有项目来击败自动参考)。这也是这里这里的意见(在我看来是正确的)。

有什么建议么?如果我不理解所有这一切,我不会感到惊讶......

4

3 回答 3

7

免责声明:虽然这对我来说之前工作得非常好,但您应该意识到依赖内部私人行为的经典陷阱。虽然我编写的测试最终会在内部实现发生变化时警告我,但我已经转向更环保的牧场。你也应该这样做。因此,在我看来,这个问题及其答案的价值只是历史性的。


对不起那个问题,我想是时候了。

为了解决这个问题,我按原样实施了这个解决方案。似乎工作得很好。所以,我相信这只是通过弄清楚它的 Id 是如何命名的来找到(当前附加的)片段实例的问题。上面的链接解释了它是如何制作的。

我选择回答我自己的问题而不是删除它,因为我相信像我这样的寻呼机新手将从“真实案例场景”中受益。我见过的大多数答案都在谈论理论,顺便说一句,这是正确的方法……但是如果没有一个真实的例子可以研究,有时像我这样的人会迷路。

无论如何,这是我需要的最后一段代码(上面的注释部分):

int n = 0;
mViewPager.setCurrentItem(n); // in the question I had stopped here.

ExcerptsFragment f = (ExcerptsFragment) ContainerActivity.this
        .getSupportFragmentManager().findFragmentByTag(getFragmentTag(n));
f.triggerRefresh();

// ... below the helper method: used the solution from the link.

private String getFragmentTag(int pos){
    return "android:switcher:"+R.id.pager+":"+pos;
}

所以,我感觉这是一个强大的解决方案,因为我没有持有任何对片段的引用(因此存在引用过时的风险)。我将自己的代码保持在最低限度,因此最大限度地减少了我做蠢事的机会。

当然,如果您有什么要补充、向我们展示、告诉我们这样做有什么问题或可以改进的地方,我会很高兴收到您的来信。

于 2012-04-05T04:23:04.377 回答
2

我自己搜索了一段时间来解决这个问题。您的方法原则上有效,但如果 Android 基类实现中的片段标记创建代码发生更改,它将破坏您的代码。这是一个非常讨厌的依赖!

更优雅的方法是扭转问题并在片段中保留基本活动的实例。在您的活动中为标签实现一个设置器,并在创建时在片段内调用它 - 那里的标签只需使用 getTag() 即可。

可以在此处找到示例实现。

于 2013-09-07T14:10:14.187 回答
0

我通过在创建时对片段使用 Wea​​kReferences 解决了这个问题。请参阅:https ://stackoverflow.com/a/23843743/734151

如果您发现此方法有任何问题,请发表评论。

于 2014-05-24T10:16:26.703 回答