35

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

我知道片段/活动之间的回调方法,但是这些回调不会更新参数?!

例如:在创建片段时,我将 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。

你怎么看待这件事?

4

6 回答 6

23

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

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

有关更多详细信息:是否可以在将片段添加到活动后将参数传递给片段?

于 2013-08-15T21:02:14.033 回答
6

我只是更改捆绑包中的值。

例子:

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

并使用新参数更新内容

于 2015-02-28T08:05:03.393 回答
4

您保存状态的方式与在 Fragment 的onSaveInstanceState回调中为活动执行的方式相同。如果您自上次更新了 URI onCreate(),您会将更新后的 URI 存储在 中Bundle,并会在onCreate(). 保存状态正是它的设计目的,通过更改 URI,您所做的就是更改状态。

于 2013-08-15T21:03:54.720 回答
1

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

片段可以被认为是 Activity 的模块化部分。这意味着当我们创建一个 Fragment 时,我们需要使其模块化和独立。

假设您需要 a Fragmentwhich 需要一个参数来操作。我们可以这样写:

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)which 防止您的 Fragment 在父 Activity 被销毁时被销毁。

于 2014-10-03T04:09:06.737 回答
0

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

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

如果您不想编写回调,则可以解决此问题的一种方法是使用 Intents 和 BroadcastReceivers (这可能有点矫枉过正且难以管理,但如果做得正确,我的经验可以省去很多麻烦)向父活动发送和接收广播。

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

于 2014-10-02T20:00:02.800 回答
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;
}
于 2016-10-12T12:59:20.513 回答