更新片段参数的最佳实践?
Posted
技术标签:
【中文标题】更新片段参数的最佳实践?【英文标题】:Best practice for updating arguments of a fragment? 【发布时间】:2013-08-18 04:09:21 【问题描述】:我知道“newInstance”-模式 (Best practice for instantiating a new android Fragment)。但是,例如,如果另一个片段更改数据,我该如何更新片段的这些参数?
我知道片段/活动之间的回调方法,但这些回调不会更新参数?!
例如:在创建片段时,我将 URI 与捆绑包一起传递给它。 然后另一个片段通过第一个片段上的 changeUri(Uri uri) 方法回调更改此 URI。 如果片段被重新创建(例如由于屏幕旋转),它将使用参数包中的第一个 URI 而不是后来更新的 uri,对吗?
解决此问题的最佳做法是什么?我是否必须手动将其存储在 savedInstanceState 中并根据使用情况决定是使用 instanceState 还是 arguments-bundle?
我正在寻找一种处理片段参数的标准方法,所以我想我会采用这种方法(伪代码):
private Uri arg1;
public static Fragment newInstance(Uri arg1)
create bundle
create fragment instance
set bundle to fragment
return fragment
private void onCreate(Bundle savedInstance)
if(savedInstance != null)
arg1 = savedInstance.uri
private Uri getUri()
if(arg1 == null)
arg1 = getArguments.uri
if(arg1 == null)
arg1 = defaultValue
所以我有一个简单统一的方式来访问我的论点。并且每次我需要该参数时都不必使用 if-else-hassle。
你怎么看?
【问题讨论】:
是的。有多少代码在谈论?一个过度的方法 -onSaveInstanceState
- 在onCreate
中有一个额外的行和一个 if-else 语句?
失败设计缺陷片段不应依赖于其他片段
如何“重写”该片段的公共方法中的参数?
【参考方案1】:
一旦将其集合和Fragment
添加到Activity
,您将无法更改参数,我使用了您自己定义的类似方法。
首先,我检查了传递给onCreate()
的Bundle
,如果它不为null,我使用它,但如果它为null,那么我使用参数。我将最新的数据保存在onSaveInstanceState()
。
更多详情:Is it possible to pass arguments to a fragment after it's been added to an activity?
【讨论】:
我强烈建议 OP 将此设置为给予适当信用的答案。【参考方案2】:我只是更改捆绑包中的值。
示例:
synchronized (fragment.getArguments())
fragment.getArguments().putInt(KEY, new Value);
并使用新参数更新内容
【讨论】:
【参考方案3】:您保存状态的方式与在 Fragment 的 onSaveInstanceState 回调中保存活动的方式相同。如果自上次 onCreate()
以来您已更新 URI,您会将更新后的 URI 存储在 Bundle
中,并会在 onCreate()
中收到此回复。保存状态正是它的设计目的,通过更改 URI,您所做的就是更改状态。
【讨论】:
【参考方案4】:更新片段参数的最佳实践:为什么我们需要通过newInstance()
方法添加参数,为什么它是片段的最佳实践?
可以将片段视为 Activity 的模块化部分。这意味着当我们创建一个 Fragment 时,我们需要使其模块化和独立。
假设你需要一个Fragment
,它需要一个参数来操作。我们可以这样写:
MyFragmentClass mFrag = new MyFragmentClass();
Bundle bundle = new Bundle();
bundle.putString("key", value);
mFrag.setArguments(bundle);
它也可以正常工作,您可以在 onCreate
方法中获取参数。区别在于:您也可以创建一个不带参数的 Fragment 实例并将其添加到 FragmentManager
,但您的 Fragment 需要参数才能操作。在 Fragment 中添加 newInstance
方法会强制开发人员在实例化 Fragment 时添加参数。这就是为什么它被称为最佳实践。
在您的问题中,您可以使用setRetainInstance(boolean retain)
,它可以防止您的 Fragment 在父 Activity 被销毁时被销毁。
【讨论】:
【参考方案5】:根据您使用片段的方式,可能会决定该策略的有效性。
例如,如果您在通用选项卡/视图分页器模式中有许多片段,并且正在使用 FragmentStatePagerAdapter 管理它们,那么您的活动或其他片段可能有机会引用不再存在的片段实例,从而导致空指针例外。
如果您不想编写回调,则可以解决此问题的一种方法是使用 Intents 和 BroadcastReceivers(这可能有点矫枉过正且难以管理,但如果操作正确,可以省去很多麻烦我的经验)向父活动发送和接收广播。
意图的美妙之处在于,它们可以调整为在特定时间工作,并接受范围广泛的额外数据,包括捆绑和可包裹对象。
【讨论】:
【参考方案6】:如果您想重用片段但需要更新参数,则需要使用 fragment.getArguments().putAll(bundle);
private static void setInspireByDoArguments(DoOptionsFragment fragment, long doId)
Bundle bundle = new Bundle();
bundle.putLong(Constants.EXTRA_DO_ID, doId);
bundle.putInt(Constants.EXTRA_DO_OPTIONS_DIALOG_MODE, MODE_GET_INSPIRE_BY_DO);
if (fragment.getArguments() != null)
fragment.getArguments().putAll(bundle);
else
fragment.setArguments(bundle);
//This is how I managed to Check if the fragment exist and update the arguments.
public static void showDoInspireDialog(FragmentManager fragmentManager, long doId, DoOptionsFragment.DoOptionCallBack callBack)
DoOptionsFragment doOptionsFragment = (DoOptionsFragment) fragmentManager.findFragmentByTag("do_options_fragment");
if (doOptionsFragment == null)
doOptionsFragment = DoOptionsFragment.getInspiredByDoInstance(doId, callBack);
fragmentManager.beginTransaction()
.add(doOptionsFragment, "do_options_fragment")
.commit();
else
doOptionsFragment.setCallBack(callBack);
setInspireByDoArguments(doOptionsFragment, doId);
doOptionsFragment.showInspireByDoDialog(doId);
public static DoOptionsFragment getInspiredByDoInstance(long doId, DoOptionsFragment.DoOptionCallBack callBack)
DoOptionsFragment doOptionsFragment = new DoOptionsFragment();
setInspireByDoArguments(doOptionsFragment, doId);
doOptionsFragment.setCallBack(callBack);
return doOptionsFragment;
【讨论】:
fragment.setArguments(bundle)
可以产生java.lang.IllegalStateException
如果你在Activity中切换回现有的片段以上是关于更新片段参数的最佳实践?的主要内容,如果未能解决你的问题,请参考以下文章
更新:在 Zend Framework 中管理静态内容的最佳实践?