Android上用于创建Fragment
的最佳做法是使用静态工厂方法,并通过Bundle
在setArguments()
中传递参数。
在Java中,这样做是这样的:
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;
}
}
在Kotlin中,这转化为:
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
}
}
}
这对于支持与Java的互操作是有意义的,所以它仍然可以通过MyFragment.newInstance(...)
调用,但是如果我们不需要担心Java互操作,那么在Kotlin中有更惯用的方法吗?
答案 0 :(得分:36)
我喜欢这样做:
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)
}
}
}
编辑:使用KotlinX扩展程序,您也可以执行此操作
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)
}
}
答案 1 :(得分:5)
inline fun <reified T : Fragment>
newFragmentInstance(vararg params: Pair<String, Any>) =
T::class.java.newInstance().apply {
arguments = bundleOf(*params)
}`
所以就像这样使用:
val fragment = newFragmentInstance<YourFragment>("key" to value)
bundleOf()
可以从Anko
答案 2 :(得分:1)
另一种方式我found here
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
}
...
}
...
}
答案 3 :(得分:1)
晚了聚会,但我相信习惯上应该是这样的:
Snap (Workshop Bookings) {
"-Lb4XzGtLtnBAgoPB6Ay" = {
"Booking Date" = 20190329;
"Booking End" = "14:00";
"Booking Id" = 201903291300;
"Booking Start" = "13:00";
"Shop Logo Url" = "https://firebasestorage.googleapis.com/v0/b/fix-it-b4b00.appspot.com/o/Spezial%20Cycle%2FSpezial%20Cycle%20logo.png?alt=media&token=016cc976-ae8d-4c71-a77f-a899d661be20";
"Shop Name" = "Spezial Cycle";
"User Name" = "";
"Works List" = "Revisione Generale, ";
};
}
具有这样的扩展名:
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)
}
}
}
或
inline fun <T : Fragment> T.withArgs(argsBuilder: Bundle.() -> Unit): T =
this.apply {
arguments = Bundle().apply(argsBuilder)
}
关键是私有常量不应该是伴随对象的一部分。
答案 4 :(得分:1)
companion object {
private const val NOTE_ID = "NOTE_ID"
fun newInstance(noteId: Int?) = AddNoteFragment().apply {
arguments =
Bundle().apply { putInt(NOTE_ID, noteId ?: Int.MIN_VALUE) }
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
arguments?.let {
noteId = it.getInt(NOTE_ID)
}
}
答案 5 :(得分:1)
我认为更优雅的方式
open class Instance<T : Fragment> {
@Suppress("UNCHECKED_CAST")
fun newInstance(vararg args: Pair<String, Any?>): T {
val cls = Class.forName(javaClass.name.substringBefore("$"))
return (cls.newInstance() as T).apply {
arguments = bundleOf(*args)
}
}
}
class MyFragment : Fragment() {
companion object : Instance<MyFragment>()
}
记住添加proguard规则来保存构造函数
-keepclassmembers class * extends androidx.fragment.app.Fragment {
<init>(...);
}
或者没有反射和proguard
open class Instance<T : Fragment>(private val cls: Class<T>) {
fun newInstance(vararg args: Pair<String, Any?>): T {
return cls.newInstance().apply {
arguments = bundleOf(*args)
}
}
}
class MyFragment : Fragment() {
companion object : Instance<MyFragment>(MyFragment::class.java)
}
使用示例
val myFragment = MyFragment.newInstance("foo" to "bar)
答案 6 :(得分:0)
Kotlin包级功能
关于Kotlin所说的使用包级功能而不是“静态”方法的事
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()
}
}