Die bewährte Methode für Android zum Erstellen einer Fragment
besteht darin, eine statische Factory-Methode zu verwenden und Argumente in einer Bundle
über setArguments()
zu übergeben.
In Java geschieht dies in etwa wie folgt:
public class MyFragment extends Fragment {
static MyFragment newInstance(int foo) {
Bundle args = new Bundle();
args.putInt("foo", foo);
MyFragment fragment = new MyFragment();
fragment.setArguments(args);
return fragment;
}
}
In Kotlin konvertiert dies zu:
class MyFragment : Fragment() {
companion object {
fun newInstance(foo: Int): MyFragment {
val args = Bundle()
args.putInt("foo", foo)
val fragment = MyFragment()
fragment.arguments = args
return fragment
}
}
}
Es ist sinnvoll, Interop mit Java zu unterstützen, sodass es immer noch über MyFragment.newInstance(...)
aufgerufen werden kann. Aber gibt es in Kotlin einen idiotischeren Weg, dies zu tun, wenn wir uns nicht mit Java-Interop befassen müssen?
Ich mache das gerne so:
companion object {
private const val MY_BOOLEAN = "my_boolean"
private const val MY_INT = "my_int"
fun newInstance(aBoolean: Boolean, anInt: Int) = MyFragment().apply {
arguments = Bundle(2).apply {
putBoolean(MY_BOOLEAN, aBoolean)
putInt(MY_INT, anInt)
}
}
}
Bearbeiten: Mit KotlinX-Erweiterungen können Sie dies auch tun
companion object {
private const val MY_BOOLEAN = "my_boolean"
private const val MY_INT = "my_int"
fun newInstance(aBoolean: Boolean, anInt: Int) = MyFragment().apply {
arguments = bundleOf(
MY_BOOLEAN to aBoolean,
MY_INT to anInt)
}
}
Spät zur Party, aber ich glaube idiomatisch sollte es so etwas sein:
private const val FOO = "foo"
private const val BAR = "bar"
class MyFragment : Fragment() {
companion object {
fun newInstance(foo: Int, bar: String) = MyFragment().withArgs {
putInt(FOO, foo)
putString(BAR, bar)
}
}
}
Mit einer Erweiterung wie dieser:
inline fun <T : Fragment> T.withArgs(argsBuilder: Bundle.() -> Unit): T =
this.apply {
arguments = Bundle().apply(argsBuilder)
}
oder
companion object {
fun newInstance(foo: Int, bar: String) = MyFragment().apply {
arguments = bundleOf(
FOO to foo,
BAR to bar
)
}
}
Der Schlüssel ist, dass die privaten Konstanten nicht Teil des Begleitobjekts sein sollten.
Ein anderer Weg, dies zu tun, ich hier gefunden
class MyFragment: Fragment(){
companion object{
private val ARG_CAUGHT = "myFragment_caught"
fun newInstance(caught: Pokemon):MyFragment{
val args: Bundle = Bundle()
args.putSerializable(ARG_CAUGHT, caught)
val fragment = MyFragment()
fragment.arguments = args
return fragment
}
...
}
...
}
Kotlin-Funktion auf Paketebene
Wie steht es mit diesem Kotlin, dass die Funktion auf Paketebene anstelle der statischen Methode verwendet wird
MyFragment.kt
class MyFragment : Fragment() {
.....
}
fun MyFragmentNewInstance(): MyFragment {
return MyFragment()
}
MyActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (supportFragmentManager.findFragmentById(R.id.fragmentContainer) == null) {
supportFragmentManager.beginTransaction()
.add(R.id.fragmentContainer, MyFragmentNewInstance())
.commit()
}
}