【问题标题】: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 语句?
  • 失败设计缺陷片段不应依赖于其他片段
  • 如何“重写”该片段的公共方法中的参数?

标签: android android-fragments


【解决方案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中切换回现有的片段
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多