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

37

我知道“newInstance”模式(最佳实践:实例化Android Fragment)。但是,如果另一个片段更改了数据,我该如何更新片段的这些参数呢?

我知道在Fragment/Activity之间使用回调方法,但这些回调不会更新参数?!

例如:在创建片段时,我使用bundle将URI传递给它。然后,另一个Fragment通过第一个Fragment上的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麻烦。

你觉得怎么样?


是的。我们在谈论多少代码?一个重写方法 - onSaveInstanceState - 有1行额外的代码和一个if-else语句在onCreate中吗? - gunar
设计缺陷,片段之间不应该相互依赖。 - danny117
那么,在该片段的公共方法中“重写”参数怎么样? - theSpyCry
6个回答

25

一旦参数设置完成并将Fragment添加到Activity中,就无法更改参数。我使用了您自己定义的类似方法。

首先,我检查传递给onCreate()Bundle,如果它不为空,则使用它,但如果为空,则使用参数。并且我在onSaveInstanceState()中保存最新的数据。

更多详情请参见:Is it possible to pass arguments to a fragment after it's been added to an activity?


2
我强烈建议楼主将此设置为答案,以便给予适当的认可。 - Nico Dumdum

8

我只是修改了bundle中的值。

示例:

synchronized (fragment.getArguments()) {
    fragment.getArguments().putInt(KEY, new Value);
}

使用新参数更新内容


4
你可以在Fragment的onSaveInstanceState回调中保存状态,方式与在Activities中保存状态相同。如果你在上次onCreate()之后更新了URI,则应将更新后的URI存储在Bundle中,并在onCreate()中接收它。保存状态正是设计此功能的目的,通过更改URI,你所做的就是更改状态。

1

更新Fragment参数的最佳实践:为什么我们需要通过newInstance()方法添加参数,并且为什么这是Fragment的最佳实践?

Fragment可以被视为Activity的模块化部分。这意味着当我们创建一个Fragment时,我们需要使它具有模块化和独立性。

假设您需要一个需要参数才能运行的Fragment。我们可以这样写:

MyFragmentClass mFrag = new MyFragmentClass();
Bundle bundle = new Bundle();
bundle.putString("key", value);
mFrag.setArguments(bundle);

它也可以正常工作,并且您可以在 onCreate 方法中获取参数。这里的区别是:您还可以实例化没有参数的片段并将其添加到 FragmentManager ,但是您的片段需要参数才能运行。在Fragment中添加 newInstance 方法会强制开发人员在实例化Fragment时添加参数。这就是为什么它被称为最佳实践的原因。

在您的问题中,您可以使用 setRetainInstance(boolean retain),它可以防止父Activity销毁时销毁您的Fragment。


0
如果您想要重复使用一个片段但需要更新参数,则需要使用 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;
}

2
如果在 Activity 中切换回现有的 Fragment,fragment.setArguments(bundle) 可能会产生 java.lang.IllegalStateException - A. Petrov

0

根据您使用片段的方式,可能会决定该策略的有效性。

例如,如果您在常见的选项卡/视图分页器模式中有许多片段,并使用FragmentStatePagerAdapter进行管理,则可能存在机会使活动或其他片段引用不再存在的片段实例,从而导致空指针异常。

如果您不想编写回调,可以使用Intents和BroadcastReceivers(可能有点过度设计和难以管理,但如果正确执行可以节省很多麻烦)来发送和接收广播到和从父活动。

关于意图的美妙之处在于它们可以调整为在特定时间工作并接受各种数据额外信息,包括捆绑包和可包裹对象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接