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

时间:2013-08-15 20:55:44

标签: android android-fragments

我知道“newInstance”-Pattern(Best practice for instantiating a new Android Fragment)。但是,如果更新数据,如何更新片段的这些参数呢?

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

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

你怎么看?

6 个答案:

答案 0 :(得分:21)

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

首先,我检查了传递给onCreate()的{​​{1}},如果它不是null我使用它,但如果它为null,那么我使用参数。我保存onSaveInstanceState()中的最新数据。

有关详情:Is it possible to pass arguments to a fragment after it's been added to an activity?

答案 1 :(得分:4)

您可以像处理片段onSaveInstanceState回调中的活动一样保存状态。如果您自上次onCreate()以来更新了URI,则会将更新后的URI存储在Bundle中,并会在onCreate()中重新收到。保存状态正是它的设计目标,通过更改URI,您所做的就是更改状态。

答案 2 :(得分:4)

我只是更改了包中的值。

示例:

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

使用新的Argument

更新内容

答案 3 :(得分:1)

Best practice for updating arguments of a fragment :为什么我们需要通过NewInstance()方法&添加参数为什么它是片段的最佳实践?

片段可以被视为活动的模块化部分。这意味着当我们创建一个片段时,我们需要使它成为模块化的。独立的。

假设你需要一个需要参数来操作的片段。我们也可以写它

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

它也很好用&你可以得到参数onCreate方法。不同之处在于您还可以在不使用参数的情况下创建片段实例,并将其添加到片段管理器中,但您的片段需要参数才能运行。在片段中添加newInstance方法会强制开发人员在创建时添加参数。这就是最佳实践的原因。

在你的问题中你可以使用setRetainInstance(boolean retain)来防止你的片段在活动被破坏时不被破坏。

答案 4 :(得分:0)

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

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

如果你不想编写回调,你可以解决这个问题的方法是使用Intents和BroadcastReceivers(这可能有点过分且难以管理,但如果正确完成可以节省很多我的经验令人头疼)向父母活动发送和接收广播。

关于意图的美妙之处在于它们可以在特定时间进行调整,并接受各种数据附加功能,包括捆绑包和可包裹的对象。

答案 5 :(得分: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;
}