0

我在我的 Android 应用程序中实现某项功能时遇到问题。

这是设置:

  • ItemPagerActivity:包含显示寻呼机的片段的活动。
  • ItemPagerFragment:包含加载其他片段的寻呼机的片段。游标用于加载片段。
  • ItemFragment:分页器中的片段,它执行异步任务来加载其数据。

我想要的是以下内容:

  • 当我滑动页面时,将当前显示的数据ItemFragment传递给ItemPagerActivity(具体来说,项目的名称将用作活动的标题)。

我已经定义了一个监听器,ItemFragment它会在加载数据时发出通知:

public class ItemFragment ... {

    public interface OnItemLoadedListener {
        public void onItemLoaded(Item item);
    }

    private Collection<OnItemLoadListener> listeners;

    private class LoadItemTask extends AsyncTask<...> {
        ...
        public void onPostExecute(Item item) {
            notifyItemLoaded(item);
            ...
        }
    }
}

如果这个片段被一个 包裹起来Activity,那么我可以简单地通过执行以下操作来设置活动的标题:

public class ItemActivity {

    public void onCreate(...) {
        ...
        ItemFragment fragment = new ItemFragment();
        fragment.registerItemLoadedListener(new ItemLoadedListener() {
            public void onItemLoaded(Item item) {
                setTitle("Item: " + item.getName());
            }
        });
        ...
    }
}

所以这很容易,并且按预期工作:当活动开始时,它会创建片段,该片段会加载项目,通知活动,并且标题会正确更新。

但是使用ItemPagerFragment,片段会被抢先加载:滑动到片段 3 可能意味着片段 4 和片段 5 已创建。加载项目时从类接收通知在ItemFragment这里是不正确的,因为显示的片段可能与执行最后加载的片段不匹配。

现在ViewPager该类有一个OnPageChangeListener可能是解决方案的方法:当我滑动时,会使用当前页码调用此侦听器。从该页码中,我需要(以某种方式)从适配器获取表示该页面的片段,从片段中获取Item数据,并通知侦听Item器现在已加载:

public class ItemPagerFragment ... {

    private Collection<OnItemLoadedListener> listeners;

    public View onCreateView(...) {
        ...
        ViewPager pager = (ViewPager) view.findViewById(R.id.pager):
        pager.setOnPageChangeListener(new OnPageChangeListener() {
            public void onPageChange(int pageNumber) {
                ItemFragment fragment = getItemFragment(pageNumber);
                Item item = fragment.getLoadedItem();
                notifyItemLoaded(item);
            }
         });
         ...
    }

}      

然后ItemPagerActivity该类将注册为ItemPagerFragment该类的侦听器,如下所示:

class ItemPagerActivity ... {

    public void onCreate(...) {
        ...
        ItemPagerFragment fragment = new ItemPagerFragment();
        fragment.registerOnItemLoadedListener(new OnItemLoadedListener() {
            public void onItemLoaded(Item item) {
                setTitle("Item: " + item.getName());
            }
        });
        ...
    }
}

这看起来不错,但有很多问题:

  • OnPageChangeListener可以在片段加载其数据之前调用 (即,在项目异步加载之前将片段滑动到视图中)。所以调用fragment.getLoadedItem()可能会返回null

  • 不会为初始OnPageChangeListener页面调用 (仅当页面更改时,例如在滑动操作之后),因此初始页面的活动标题将不正确。

  • 该类ViewPager只允许一个OnPageChangeListener. 这是一个问题,因为我也在使用ViewPageIndicator库,它想为ViewPager.

我假设这种模式(通知已刷入视图的片段中的数据活动)可能很常见,所以我想知道这种模式是否有任何好的解决方案,以及我遇到的三个具体问题上面已经确定了。

4

2 回答 2

0

...所以我想知道这种模式是否有任何好的解决方案,以及我上面确定的三个具体问题。

我不知道我是否会称它为模式,但这OnPageChangeListener是要走的路。

OnPageChangeListener 可以在片段加载其数据之前被调用(即,片段在异步加载项之前被滑动到视图中)。所以对 fragment.getLoadedItem() 的调用可能会返回 null。

首先,您的代码应该从一开始就处理“没有可用数据的情况”。您AsyncTasks将负责加载数据并仅在他们正在处理的片段是可见片段时才更新标题(针对'方法ItemFragment进行测试的位置字段)。将在加载数据处理标题的更新,因为用户在页面之间切换并且数据可用(如果没有数据可用,它将返回 null)。要获得某个职位,您可以使用以下代码:ViewPagergetCurrentItem()OnPageChangeListenerItemFragment

    ItemFragment itf = getSupportFragmentManager()
            .findFragmentByTag(
                    "android:switcher:" + R.id.theIdOfTheViewPager + ":"
                            + position);
    if (itf != null) {
        Item item = fragment.getLoadedItem();
            notifyItemLoaded(item);
    }

OnPageChangeListener 不会为初始页面调用(仅当页面更改时,例如在滑动操作之后),因此初始页面的活动标题将不正确。

往上看。

ViewPager 类只允许一个 OnPageChangeListener。这是一个问题,因为我也在使用 ViewPageIndicator 库,它想为 ViewPager 分配一个侦听器

我承认我对ViewPagerIndicator图书馆知之甚少,但快速浏览它的网站,我看到:

(可选)如果您将 OnPageChangeListener 与视图寻呼机一起使用,您应该在指示器中而不是直接在寻呼机上设置它。

titleIndicator.setOnPageChangeListener(mPageChangeListener);

我看不出限制在哪里。

于 2012-12-14T15:06:51.267 回答
0

出于我的目的,当片段可见时,它可以ViewPager.OnPageChangeListener.onPageSelected()与 结合使用Fragment.onActivityCreated()来执行操作。Fragment.getUserVisibleHint()也有帮助。

于 2013-07-07T22:51:24.063 回答