18

新的导航组件很棒!但是我想在我的片段之间发送“长”变量。

在导航图文件中写这个是有效的:

<argument
        android:name="discussionId"
        app:type="string" />

写这个不会编译:

<argument
        android:name="discussionId"
        app:type="long" />

目前,我似乎被迫将它们解析为字符串格式。它工作得很好,但对我来说似乎很奇怪,对于这样一个基本架构,我不能使用诸如 long 或 byte 或 short 之类的原始类型。我错过了什么吗?未来会开发这种功能集吗?

4

5 回答 5

32

从 1.0.0-alpha08 版本开始,你可以使用很多不同的类型,我在这里找到了一个列表

"integer" -> IntType
"integer[]" -> IntArrayType
"long" -> LongType
"long[]" -> LongArrayType
"float" -> FloatType
"float[]" -> FloatArrayType
"boolean" -> BoolType
"boolean[]" -> BoolArrayType
"reference" -> ReferenceType
"reference[]" -> ReferenceArrayType
"string" -> StringType
"string[]" -> StringArrayType
null -> StringType

和用于导航图中的(例如:字符串列表)

<argument
    android:name="photo_url"
    app:argType="string[]"
/>
于 2018-12-26T08:22:08.760 回答
18

目前,除了integerstringinferredreference之外,您不能使用安全的 args 类型。已打开一个问题,要求提供其他类型。

但是在使用navigate()方法导航到目的地时,您以编程方式传递了一个包:

var bundle = bundleOf("key" to amount)
view.findNavController().navigate(R.id.action_id, bundle)

您可以使用通常getArguments的方法来检索目标片段中的数据:

val value = arguments.getString("key")
于 2018-06-19T18:27:04.367 回答
6

使用原始包装器!它出什么问题了?

<argument
    android:name="discussionId"
    app:argType="java.lang.Long" />

// java.lang.Double, java.lang.Float, etc...

使用 kotlin 甚至使用安全 args 都像魅力一样工作,因为所有原始包装器都在实现Serializable

于 2019-05-22T13:44:39.533 回答
0

只需将默认值设置为 0L 而不是 0,并将类型设置为“推断”

于 2018-07-18T04:08:46.207 回答
0

这可能来晚了,并以稍微不同的方式解决了问题,但我把它放在这里是因为我觉得这个问题需要一种在导航期间发送参数的方式,并以一种类型安全的方式发送到标称量级。

我的朋友是架构组件视图模型以非常有效的方式解决的问题之一。根据文档,在“片段之间共享数据”部分,我们将找到所使用的技术。本质上,这一切都是关于创建一个视图模型实例,该实例被附加到两个(或更多)导航到片段的封闭片段/活动的范围内。这样,它们将在导航到片段的整个生命周期中存活下来。

下面是一个小例子,我实际上是从我在生产中的一个应用程序中提取的。

-MainActivity |-NavHostFragment | |-FormFragment(Start destination) | |-ResultFragment( navigated to fragment) | | 以及用于在目标片段之间传输数据的 SharedViewModel。

查看模型代码

public class SharedViewModel extends ViewModel implements ResultFragment.ResultFragmentViewModel, FormFragment.FormFragmentViewModel {
public String name;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}   }

在 FormFragment 中。

    @Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    sharedViewModel = ((FormFragmentViewModel) ViewModelProviders.of(this.getActivity()).get(SharedViewModel.class));
}

public void onFabPressed( View view) {
    String text = editText.getText().toString().trim();
    if(text.matches("")) return ;
    sharedViewModel.setName(text);
    Navigation.findNavController(view).navigate(R.id.action_formFragment_to_resultFragment);

}

public interface FormFragmentViewModel {
    public void setName(String string);
}

在结果片段中,

    @Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    sharedViewModel = ((ResultFragmentViewModel) ViewModelProviders.of(this.getActivity()).get(SharedViewModel.class));
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_result, container, false);
    FloatingActionButton fab = view.findViewById(R.id.fab);
    ((TextView) view.findViewById(R.id.textview))
        .setText(sharedViewModel.getName());
    fab.setOnClickListener(
            Navigation.createNavigateOnClickListener(R.id.action_global_formFragment)
    );
    return view;
}


public interface ResultFragmentViewModel {
    public String getName();
}

在上面的代码中,重点应该放在发送到作为封闭活动的两个片段的 ViewModelProviders.of() 方法的范围上,因为它的生命周期比两个片段(FormFragment、ResultFragment)的生命周期都要长。在导航到目标 Fragment 之前保存我们希望发送到 viewmodel 中的目标 Fragment 的数据,知道我们将在目标 Fragment 中从 ViewModel 的同一实例中检索它。这些接口用于 android studio 的智能感知,从视图模型中抽象出(从开发人员的角度来看)不必要的方法,这些方法对应于它正在使用的片段。在这个设置中,甚至可以使用类似的东西将动作发送到目标片段委托模式通过将对象设置为在视图模型的目标片段中执行一次操作,然后导航到目标片段并在那里检索对象并将要执行的操作委托给它。我想在这个设置中补充一点,几乎不可能将String name变量与 int 混淆。

希望这可以帮助。

于 2018-12-27T08:02:51.763 回答