是否可以在 android 的新导航组件中发送字符串或整数以外的参数

Is it possible to send arguments other than string or integer in android's new navigation component

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

将此写入导航图文件有效:

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

写这个不会编译:

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

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

目前您不能使用除整数字符串[=28以外的类型的安全参数=]、推断参考issue 已打开要求其他类型。

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

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

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

val value = arguments.getString("key")

只需将默认值设置为 0L 而不是 0,并将类型设置为 "inferred"

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

"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[]"
/>

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

我的朋友是问题之一 architecture components viewmodel solves in a very efficient manner.As per the docs,在 "share data between fragments" 部分我们将找到所使用的技术。本质上,这都是关于创建一个 viewmodel 实例,而不是附加到封闭 fragment/activity 到两个(或更多)导航到片段的范围。这样,它们将在导航到片段的整个生命周期中存活。

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

-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);
}

在ResultFragment中,

    @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() 方法的范围是封闭的 activity,因为它的生命周期超过两个片段的生命周期(FormFragment,ResultFragment)。在导航到目标片段之前,将我们希望发送到视图模型中的目标片段的数据保存下来,因为我们知道我们将从目标片段中的同一视图模型实例中检索一次数据。 这些接口用于 android studio 的智能感知,从视图模型中抽象出(从开发人员的角度来看)不必要的方法,分别用于它在哪个片段中使用。在此设置中,甚至可以将操作发送到目的地使用类似 delegate pattern 的片段,通过将对象设置为在导航到目标片段之前在视图模型中的目标片段中执行一次操作,然后在那里检索对象并将要采取的操作委托给它。我想补充一点,在此设置中,几乎不可能将 String name 变量与 int.

混淆

希望对您有所帮助。

使用原始包装器!怎么了?

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

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

与 kotlin 甚至安全参数一起工作就像一个魅力,因为所有原始包装器都在实现 Serializable