我有一个最多可显示4个片段的ViewPager。在任何给定时间可用的数量是动态的(可以是1,2,3或4)。让这些片段自我管理是最有意义的。我的意思是他们是单身人士。我没有使用new关键字创建新片段,而是编写了一个'getInstance(String key)'方法,该方法尝试从地图中检索指定键的片段,或者如果映射中不存在,则创建一个新实例,使用给定键将片段放在映射中,使用包含该键的包设置片段参数,以便片段可以在onCreate()上检索它,然后返回该片段的新实例。
对于那些没有关注的人,这里是代码:
public class DishListFragment extends ListFragment {
public static final String MENU = "menu";
...
private static Map<String, DishListFragment> mInstances = new HashMap<String, DishListFragment>();
public static DishListFragment getInstance(String menuKey) {
if (mInstances.containsKey(menuKey))
return mInstances.get(menuKey);
Bundle b = new Bundle();
b.putString(MENU, menuKey);
DishListFragment dlf = new DishListFragment();
dlf.setArguments(b);
mInstances.put(menuKey, dlf);
return dlf;
}
}
您可能已经注意到这不是线程安全的。
OnCreate,我的主要活动设置其视图然后产生一个AsyncTask负责从服务器获取数据,该服务器将填充我的DishListFragments。同时,主要活动继续并设置PagerAdapter。当PagerAdapter请求新的DishListFragment时,该数字将动态转换为一个键,并从DishListFragment.getInstance(key)转换为值;方法被返回。最初,ListFragments观察到的内容类具有虚拟数据,因此总会显示一个页面,因此ViewPager始终有一个页面可供显示。
AsyncTask启动时,会显示进度对话框。完成后,它会关闭进度对话框并调用我的活动中的方法,然后在我的内容类中设置数据。然后调用一个方法refresh(),该方法告诉现有的所有DishListFragments通知其适配器数据集已更改。该方法完成后,将通知ViewPagerAdapter其数据集已更改。
在我的主要活动中:
public void onRetrieveData(Result result) {
switch(result.getCode()) {
case Result.SUCCESS:
Log.i(UITHREAD, "Menu successfully loaded!");
/* On SUCCESS the MenuContent class should be given the data and
* the adapters notified. */
mRequestedDate = mPendingDate;
MenuContent.setMenuData(result.getValue());
DishListFragment.refresh();
mMenuPagerAdapter.notifyDataSetChanged();
...
}
}
DishListFragment类中的refresh方法:
public static void refresh() {
for (String key : mInstances.keySet()) {
mInstances.get(key).mListAdapter.notifyDataSetChanged();
Log.d("glic", "DishListFragment: " + key + " refreshed");
}
Log.d("glic", "DishListFragments refreshed");
}
问题是,在冷启动时,除了第一页之外的所有内容都会更新。此外,从我的Logcat输出中,我收集到我的地图中只有一个DishListFragment:
10-18 22:11:41.624: I/##############(16802): Menu successfully loaded!
10-18 22:11:41.744: D/glic(16802): DishListFragment: breakfast refreshed
10-18 22:11:41.744: D/glic(16802): DishListFragments refreshed
10-18 22:11:41.744: D/GLIC(16802): lunch
但是,我的视图寻呼机显示4个页面,第一个页面仍然包含虚拟数据。如果我旋转屏幕,则会更新第一页并显示正确的信息。此外,如果我在虚拟列表中选择一个项目,则会显示一个详细信息片段,其中包含我选择的项目位置的真实(来自服务器)信息 - 即使我只选择了一个虚拟项目。
我的第一个想法是我可能有两个单例碎片实例。一个包含带有初始虚拟数据的片段的映射,另一个包含从服务器返回的实际数据。我想这是可能的,因为我的单例不是线程安全的。但是,我不认为这会导致任何问题。我的DishListFragments不包含它们显示的数据,它们只观察它,所以不管我可能有多少个相同的 DishListFragment实例(同一个是同一页面),它们都应该观察相同的数据并且不应显示不同的数据 - 当解析并添加来自服务器的新数据时,将清除虚拟数据。
但是,我的mInstances映射的两个实例可以解释为什么视图没有更新。也许只有其中一组DishListFragments中的适配器被通知其数据集已更改。根据我的Logcat, breakfast ,这是我的第一页和填充虚拟数据的那个,确实被通知其数据集已经改变。有趣的是,其他人不是。
所以,至于我原来的问题:我是否正确实现了单个碎片分组?如果是这样,还有哪些其他因素可能导致我遇到的奇怪行为。提前致谢(=