新しいナビゲーションコンポーネントはすばらしいです。ただし、フラグメント間で「長い」変数を送信したいと思います。
これをナビゲーショングラフファイルに書き込むと機能します。
<argument
Android:name="discussionId"
app:type="string" />
これを書いてもコンパイルされません:
<argument
Android:name="discussionId"
app:type="long" />
現在、私はそれらを文字列形式との間で解析することを余儀なくされているようです。正常に動作しますが、そのような基本的なアーキテクチャーには、long、byte、shortなどのプリミティブ型を使用できないのは奇妙に思えます。何か不足していますか?このような機能セットは将来開発される予定ですか?
現時点では、できないinteger、string、inferredおよびreference。他のタイプを要求する issue が開かれました。
しかし、navigate()メソッドを使用して宛先に移動するときに、プログラムでbundleを渡します。
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[]"
/>
プリミティブラッパーを使用してください!どうしたの?
<argument
Android:name="discussionId"
app:argType="Java.lang.Long" />
// Java.lang.Double, Java.lang.Float, etc...
すべてのプリミティブラッパーがSerializable
を実装しているため、kotlinや安全な引数でさえチャームのように機能します
デフォルト値を0ではなく0Lに設定し、タイプを「推論」に設定するだけです
これは遅くなる可能性があり、少し異なる方法で問題を解決しますが、ナビゲーション中に引数を送信し、タイプセーフな方法で名目上の大きさに送信する方法に対する質問の要求を感じるため、ここに配置します。
私の友人が問題の1つであること architecture components viewmodel は非常に効率的な方法で解決します。- docs のとおり、「フラグメント間でデータを共有する」セクションでは、使用される技術。基本的に、それは、代わりに、フラグメントにナビゲートされた2つ(またはそれ以上)を囲むフラグメント/アクティビティのスコープにアタッチされるviewmodelインスタンスの作成に関するものです。そうすることで、ナビゲートされたフラグメントのライフサイクル全体を通して存続します。
以下は、本番環境にあるアプリケーションの1つから実際に抽出した小さな例です。
-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();
}
上記のコードでは、両方のフラグメント(FormFragment、ResultFragment)のライフサイクルよりもライフサイクルが長くなるため、囲みアクティビティである両方のフラグメントのViewModelProviders.of()メソッドに送信されるスコープを重要視する必要があります。宛先フラグメントに移動する前に、宛先フラグメントに送信するデータをビューモデルに保存します。宛先フラグメントでビューモデルの同じインスタンスからデータを1回取得することになります。インターフェイスは、Android studio、開発者の観点から)それが使用されているフラグメントにそれぞれ対応するビューモデルから不要なメソッドを抽象化してインテリセンスに使用されます。このセットアップでは、アクションでも delegate pattern のようなものを使用して宛先フラグメントに送信されます。宛先モデルに移動する前にビューモデルの宛先フラグメントで1回アクションを実行するようにオブジェクトを設定し、その間にオブジェクトを取得してデリゲートします。この設定に追加したいのは、intのString name
変数を混乱させるのはほぼ不可能です。
お役に立てれば。