新的导航组件非常棒!但是我想在我的片段之间发送“长”变量。
在导航图文件中写这个工作:
<argument
android:name="discussionId"
app:type="string" />
写这个不会编译:
<argument
android:name="discussionId"
app:type="long" />
目前,似乎我不得不将它们解析为字符串格式。它工作正常,但对我来说似乎很奇怪,我不能使用诸如long或byte或short这样的基本架构之类的原始类型。我错过了什么吗?这种功能是否会在未来开发?
目前,您不能使用除整数,字符串,推断和引用之外的类型的安全args。一个issue已经开放,要求其他类型。
但是,在使用navigate()方法导航到目标时,以编程方式传递包:
var bundle = bundleOf("key" to amount)
view.findNavController().navigate(R.id.action_id, bundle)
您可以使用通常的getArguments
来检索目标片段中的数据:
val value = arguments.getString("key")
从版本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[]"
/>
只需将默认值设置为0L而不是0,并将类型设置为“推断”
这可能会迟到并以稍微不同的方式解决问题,但我把它放在这里是因为我觉得这个问题需要一种在导航过程中发送参数的方法,以及以类型安全的方式发送名义大小的方法。
我的朋友是architecture components viewmodel s以非常有效的方式解决问题之一。根据docs,在“分享片段之间的数据”部分,我们将找到使用的技术。本质上,所有这些都是关于创建一个viewmodel实例,而是将其附加到封闭片段/活动的范围,导航到两个(或更多)导航到片段。这样,它们将在导航到片段的整个生命周期中存活。
下面是我从生产中的一个应用程序中实际提取的一个小例子。
-MainActivity
|-NavHostFragment
| |-FormFragment(Start destination)
| |-ResultFragment( navigated to fragment)
| |
和SharedViewModel用于在目标片段之间传输数据。
ViewModelCode
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()方法的范围上,这两个片段是封闭活动,因为它的生命周期比两个片段(FormFragment,ResultFragment)的生命周期都要长。在导航到目标片段之前,将我们希望发送到目标片段的数据保存到目标片段中,知道我们将在目标片段中从viewmodel的同一实例中检索它一次。这些接口用于与android studio进行智能感知,从视图模型中抽象出(从开发人员的角度来看)与视图模型相对应的不必要的方法。在这个设置中,甚至可以使用类似的东西将动作发送到目标片段delegate pattern通过在导航到目标片段之前将对象设置为在viewmodel中的目标片段中执行一次,然后检索对象并将其委托给它采取的操作。我想补充一点,在这个设置中,将String name
变量混淆为int几乎是不可能的。
希望这可以帮助。
使用原始包装!它出什么问题了?
<argument
android:name="discussionId"
app:argType="java.lang.Long" />
// java.lang.Double, java.lang.Float, etc...
像kotlin的魅力,甚至安全的args,因为所有原始包装正在实施Serializable