ViewPager 和碎片 — 保持片段状态的正确方法是什么?
碎片似乎非常适合逻辑分离 UI 在某些模块上。 但是一起。
他的生命周期对我来说仍然有雾。 所以大师的想法非常必要!
编辑
看到下面的一个愚蠢的解决方案 ;-/
规模
主要活动有
用碎片。 这些碎片可以为他人实现一些不同的逻辑。 /更换/ 操作,因此这些片段通过在Action中通过回调界面填充。 一切都在第一次发布时正常工作,但是!....
问题
在重建行动时 /例如,在更改方向时/, 与碎片发生一样
. 代码 /你会在下面找到/ 说每次创建一个动作时,我都会尝试创建一个新的片段适配器
, 与碎片相同 /也许这是问题/, 但 FragmentManager 已经让所有这些碎片在某处 /在哪里?/ 并为他们推出娱乐机制。 因此,娱乐机制导致碎片 "old" onAttach, onCreateView 等等。使用我的回调接口,使用实现的操作方法调用数据初始化。 但此方法表示新创建的片段,它是使用该方法创建的 onCreate 行动。
问题
也许我使用错误的模板,但即使在书中 Android 3 Pro 关于这个小说。 所以 ,
不客气
, 给我一个或两个震惊,并指定如何正确。 非常感谢!
代码
主要活动
BasePagerActivity 助理AK。
适配器
分段
决定
一个愚蠢的解决方案是在里面保持碎片 onSaveInstanceState /HOSTA活动/ 通过 putFragment 并让他们里面 onCreate 穿过 getFragment. 但我仍然有一种奇怪的感觉,一切都不应该工作......请参阅下面的代码:
</message></message></string,></string,></string,></string,>
ViewPager
他的生命周期对我来说仍然有雾。 所以大师的想法非常必要!
编辑
看到下面的一个愚蠢的解决方案 ;-/
规模
主要活动有
ViewPager
用碎片。 这些碎片可以为他人实现一些不同的逻辑。 /更换/ 操作,因此这些片段通过在Action中通过回调界面填充。 一切都在第一次发布时正常工作,但是!....
问题
在重建行动时 /例如,在更改方向时/, 与碎片发生一样
ViewPager
. 代码 /你会在下面找到/ 说每次创建一个动作时,我都会尝试创建一个新的片段适配器
ViewPager
, 与碎片相同 /也许这是问题/, 但 FragmentManager 已经让所有这些碎片在某处 /在哪里?/ 并为他们推出娱乐机制。 因此,娱乐机制导致碎片 "old" onAttach, onCreateView 等等。使用我的回调接口,使用实现的操作方法调用数据初始化。 但此方法表示新创建的片段,它是使用该方法创建的 onCreate 行动。
问题
也许我使用错误的模板,但即使在书中 Android 3 Pro 关于这个小说。 所以 ,
不客气
, 给我一个或两个震惊,并指定如何正确。 非常感谢!
代码
主要活动
public class DashboardActivity extends BasePagerActivity implements OnMessageListActionListener {
private MessagesFragment mMessagesFragment;
@Override
protected void onCreate/Bundle savedInstanceState/ {
Logger.d/"Dash onCreate"/;
super.onCreate/savedInstanceState/;
setContentView/R.layout.viewpager_container/;
new DefaultToolbar/this/;
// create fragments to use
mMessagesFragment = new MessagesFragment//;
mStreamsFragment = new StreamsFragment//;
// set titles and fragments for view pager
Map<string, fragment=""> screens = new LinkedHashMap<string, fragment="">//;
screens.put/getApplicationContext//.getString/R.string.dashboard_title_dumb/, new DumbFragment///;
screens.put/getApplicationContext//.getString/R.string.dashboard_title_messages/, mMessagesFragment/;
// instantiate view pager via adapter
mPager = /ViewPager/ findViewById/R.id.viewpager_pager/;
mPagerAdapter = new BasePagerAdapter/screens, getSupportFragmentManager///;
mPager.setAdapter/mPagerAdapter/;
// set title indicator
TitlePageIndicator indicator = /TitlePageIndicator/ findViewById/R.id.viewpager_titles/;
indicator.setViewPager/mPager, 1/;
}
/* set of fragments callback interface implementations */
@Override
public void onMessageInitialisation// {
Logger.d/"Dash onMessageInitialisation"/;
if /mMessagesFragment != null/
mMessagesFragment.loadLastMessages//;
}
@Override
public void onMessageSelected/Message selectedMessage/ {
Intent intent = new Intent/this, StreamActivity.class/;
intent.putExtra/Message.class.getName//, selectedMessage/;
startActivity/intent/;
}
BasePagerActivity 助理AK。
public class BasePagerActivity extends FragmentActivity {
BasePagerAdapter mPagerAdapter;
ViewPager mPager;
}
适配器
public class BasePagerAdapter extends FragmentPagerAdapter implements TitleProvider {
private Map<string, fragment=""> mScreens;
public BasePagerAdapter/Map<string, fragment=""> screenMap, FragmentManager fm/ {
super/fm/;
this.mScreens = screenMap;
}
@Override
public Fragment getItem/int position/ {
return mScreens.values//.toArray/new Fragment[mScreens.size//]/[position];
}
@Override
public int getCount// {
return mScreens.size//;
}
@Override
public String getTitle/int position/ {
return mScreens.keySet//.toArray/new String[mScreens.size//]/[position];
}
// hack. we don't want to destroy our fragments and re-initiate them after
@Override
public void destroyItem/View container, int position, Object object/ {
// TODO Auto-generated method stub
}
}
分段
public class MessagesFragment extends ListFragment {
private boolean mIsLastMessages;
private List<message> mMessagesList;
private MessageArrayAdapter mAdapter;
private LoadMessagesTask mLoadMessagesTask;
private OnMessageListActionListener mListener;
// define callback interface
public interface OnMessageListActionListener {
public void onMessageInitialisation//;
public void onMessageSelected/Message selectedMessage/;
}
@Override
public void onAttach/Activity activity/ {
super.onAttach/activity/;
// setting callback
mListener = /OnMessageListActionListener/ activity;
mIsLastMessages = activity instanceof DashboardActivity;
}
@Override
public View onCreateView/LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState/ {
inflater.inflate/R.layout.fragment_listview, container/;
mProgressView = inflater.inflate/R.layout.listrow_progress, null/;
mEmptyView = inflater.inflate/R.layout.fragment_nodata, null/;
return super.onCreateView/inflater, container, savedInstanceState/;
}
@Override
public void onActivityCreated/Bundle savedInstanceState/ {
super.onActivityCreated/savedInstanceState/;
// instantiate loading task
mLoadMessagesTask = new LoadMessagesTask//;
// instantiate list of messages
mMessagesList = new ArrayList<message>//;
mAdapter = new MessageArrayAdapter/getActivity//, mMessagesList/;
setListAdapter/mAdapter/;
}
@Override
public void onResume// {
mListener.onMessageInitialisation//;
super.onResume//;
}
public void onListItemClick/ListView l, View v, int position, long id/ {
Message selectedMessage = /Message/ getListAdapter//.getItem/position/;
mListener.onMessageSelected/selectedMessage/;
super.onListItemClick/l, v, position, id/;
}
/* public methods to load messages from host acitivity, etc... */
}
决定
一个愚蠢的解决方案是在里面保持碎片 onSaveInstanceState /HOSTA活动/ 通过 putFragment 并让他们里面 onCreate 穿过 getFragment. 但我仍然有一种奇怪的感觉,一切都不应该工作......请参阅下面的代码:
@Override
protected void onSaveInstanceState/Bundle outState/ {
super.onSaveInstanceState/outState/;
getSupportFragmentManager//
.putFragment/outState, MessagesFragment.class.getName//, mMessagesFragment/;
}
protected void onCreate/Bundle savedInstanceState/ {
Logger.d/"Dash onCreate"/;
super.onCreate/savedInstanceState/;
...
// create fragments to use
if /savedInstanceState != null/ {
mMessagesFragment = /MessagesFragment/ getSupportFragmentManager//.getFragment/
savedInstanceState, MessagesFragment.class.getName///;
StreamsFragment.class.getName///;
}
if /mMessagesFragment == null/
mMessagesFragment = new MessagesFragment//;
...
}
</message></message></string,></string,></string,></string,>
没有找到相关结果
已邀请:
10 个回复
卫东
赞同来自:
添加片段K. FragmentManager, 它使用基于特定位置的特殊标签,其中将放置片段。
仅在此职位不存在片段时才会调用。 转弯后 Android 注意 , 他已经创造了/为这个特定位置保存了一个片段,因此他只是试图再次连接他
, 而不是创造一个新的。 使用该方法时,所有这些都是免费的
, 这就是片段初始化代码通常在方法中的原因
.
即使我们没有使用
, 每次都没有忍受创造一个新的片段
. 正如您在添加片段的情况下已经注意到的那样 FragmentManager, 转动后将为您重新创建,并且无需再次添加它。 在使用碎片时,这是错误的常见原因。
使用碎片时的通常方法如下:
使用
我们将控制片段传送到适配器,不应执行上述步骤。 默认情况下,它将仅在前部和背面预加载一个片段 /虽然如果你不使用他并没有摧毁它们
/., 这是控制的
http://developer.android.com/r ... %2529
. 因此,适配器外部的片段上的直接呼叫方法不保证,因为它们甚至可能甚至不活跃。
简而言之,你决定使用
, 能够随后得到一个链接,没有那么疯狂,与使用碎片的通常方法没有那么不同 /更高/. 否则,很难获得链接,因为适配器添加了片段,而不是您个人的。 只是确保这一点
它足以在任何时候加载所需的碎片,因为您依赖于其存在。 它需要延迟装载的可能性 ViewPager, 但似乎这就是你想要的申请。
另一种方法是覆盖
并将链接保存到从Supervonka返回之前退回的片段 /如果他已经存在,他有逻辑找到片段/.
对于更完整的图片,请看看一些来源
http://grepcode.com/file/repos ... v%3Df
/短的/ 和
http://grepcode.com/file/repos ... v%3Df
/长/.
喜特乐
赞同来自:
并提到覆盖
, 保存要创建的链接
, 所以你可以稍后工作。 它也应该与之合作
; 有关详细信息,请参阅注释。
这是如何获得链接的简单示例
, 回来
, 哪个不依赖于内部集
在
. 关键是覆盖
http://grepcode.com/file/repos ... %2383
并在那里保存链接
和
不是V.
.
或者
如果您愿意与之合作
而不是类成员变量/链接
, 你也可以捕获
, 放
以同样的方式:
NOTE: 这不适用于
, 因为它没有安装
创造自己的时候
.
请注意,此方法不认为模仿内部
, 已确立的
, 而是使用权利 APIs 为了他们的提取。 所以即使
改变未来版本
, 你仍然是安全的。
不要忘记
, 依赖于你的设计
,
, 您正在尝试处理您是否仍然存在,但可能不存在,因此您必须考虑到这一点,进行检查
在使用您的链接之前。
除了 , 如果代替
这你合作
, 然后你不想保持紧张的联系
, 因为你可能有很多它们,并且严格的链接将在内存中忽略它们。 相反,保存链接
在变量中
而不是标准。 类似于这个:
</fragment></fragment>
龙天
赞同来自:
正如你所看到的那样
http://grepcode.com/file/repos ... 28int,int%29
, 碎片管理
, 商店B.
在标记下由:
- 这是
,
- 这是您的实例
.
- 这是片段的位置。 因此,您可以保存对象标识符
:
如果您想联系此碎片,您可以获得 if 的
, 例如:
诸葛浮云
赞同来自:
我的情况
- 我正在创造 / 我动态添加页面并将它们移动到 ViewPager, 但是在旋转时 /onConfigurationChange/ 我得到了一个新的页面,因为当然 OnCreate 再次打电话。 但我想保存到旋转前创建的所有页面的链接。
问题
- 我创建的每个片段都没有唯一标识符,因此唯一的参考方式是在转动后的数组中以某种方式保存链接/配置更改。
圆形的
关键概念是采取行动 /显示碎片/ 还管理了对现有片段的一系列引用,因为此操作可以使用包 onSaveInstanceState
因此,在此活动的框架内,我声明私人参与者来跟踪开放页面。
它每次都更新 onSaveInstanceState 叫做并恢复 onCreate
..因此,一旦保存,它就可以删除......
这些是主要活动的必要变化,因此我需要我的成员和方法 FragmentPagerAdapter, 所以它在里面工作
相同的设计 /如上所示 MainActivity /
和这种同步 /如上所述 onSaveInstanceState/ 通过方法支持
最后,在碎片类中
为了让所有这项工作,首先有两个变化
然后加入它 onCreate, 这样碎片没有被摧毁
我仍然在缠绕碎片和生命周期周围的过程中 Android, 因此,这里的警告在于,在这种方法中可能存在冗余/效率低下。 但它适合我,我希望它对其他具有类似案例的人有用。
</fragment></fragment></fragment></fragment></fragment></fragment></fragment>
卫东
赞同来自:
在打电话之前
, 然后在创建活动时重新创建它们:
你不能删除它们
, 否则,您将获得此异常:
Can not perform this action after
以下是页面适配器中的代码:
我只是保留当前页面并恢复它
, 在碎片创造之后。
三叔
赞同来自:
? 您必须使用标准寻呼机适配器之一
, 或者
, 取决于你是否想要不再需要的碎片
, 或者附近储存 /第一的/, 或者保持其状态 /第二/ 如有必要,它是重新创建的。
使用示例代码
能够被找到的
http://developer.android.com/t ... mples
确实,在实例之间管理表示寻呼机中的片段 activity 有点困难,因为
该框架负责保存状态并恢复寻呼机所做的任何活动碎片。 所有这些实际上都意味着初始化期间的适配器必须确保它与任何恢复的片段重新连接。 你可以看看代码
或者
, 看它是如何完成的。
君笑尘
赞同来自:
确保你打电话
BEFORE 你打电话
随传随到
...ViewPager
立即地
调用您的适配器并尝试获取碎片。 它可以发生在之前 ViewPager 将有机会恢复碎片 savedInstanceState/因此,创建无法从中重新初始化的新片段 SavedInstanceState, 因为他们是新的/.
卫东
赞同来自:
这是一个适配器代码 /这里没有什么奇怪的是,除了这个事实
- 这是活动支持的片段列表。/
这个磁通量的整个问题是获得与碎片的链接 "old", 因此,我在操作中使用此代码 onCreate.
当然,如果需要,您可以另外配置此代码,例如,确保片段是某个类的实例。
郭文康
赞同来自:
对于一点更大的加工,我自己写了自己的 ArrayList 为我的 PageAdapter, 得到一个片段 viewPagerId 和 FragmentClass 在任何位置:
所以只是创造 MyPageArrayList 用碎片:
并将它们添加到 viewPager:
之后,您可以使用其类更改方向正确片段后:
</mypagebuilder></mypagebuilder></mypagebuilder>
诸葛浮云
赞同来自:
在你的职业之前。
这不起作用这样做: