更新片段参数的最佳实践?

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中切换回现有的片段

以上是关于更新片段参数的最佳实践?的主要内容,如果未能解决你的问题,请参考以下文章

android片段-数据传递-最佳实践[重复]

在android中使用底部导航的最佳实践:活动与片段

在另一个活动托管的片段之间传递数据的最佳实践

更新:在 Zend Framework 中管理静态内容的最佳实践?

不使用支持库的 Android 4.0、4.1 (<4.2) 中嵌套片段的最佳实践

getForm() symfony2.8 后更改表单对象默认参数的最佳实践