Android Kotlin中Activity能否使用newInstance()及Fragment实例化报错解决
核心问题梳理
- 抽象类
FragmentA不需要实现newInstance():抽象类本身无法被实例化,给它加创建实例的方法完全没有意义,直接删除这部分伴生对象代码即可。 Fragment禁止通过构造函数传参:Android系统在内存不足等场景下会销毁并重建Fragment,重建时只会调用Fragment的无参构造函数,你自定义了带参数的构造函数、没有保留无参构造,就会抛出你遇到的NoSuchMethodException: <init> []报错。Activity不需要写newInstance():Activity的实例化由系统负责,你手动写的创建方法不会被系统调用,完全无用,直接删除即可。- 直接把Activity实例传入Fragment会导致内存泄漏,属于错误用法,Fragment需要关联的Context/Activity时,可以通过
requireContext()、requireActivity()方法直接获取,不需要传参。
最优解决方案
按照官方规范实现FragmentB的newInstance(),参数通过Bundle传递,系统重建时Bundle会被保留,不会丢失参数。
修正后的FragmentA.kt
abstract class FragmentA: BottomSheetDialogFragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setStyle(DialogFragment.STYLE_NORMAL, getStyle) } }
修正后的FragmentB.kt
class FragmentB : FragmentA() { // 定义接收参数的变量 private lateinit var parameterss: AnyParametersHere companion object { private const val ARG_PARAM = "arg_param" const val TAG = "FragmentB" // newInstance接收参数,存入Bundle fun newInstance(param: AnyParametersHere): FragmentB { val fragment = FragmentB() val args = Bundle() args.putParcelable(ARG_PARAM, param) // 如果是自定义类型要实现Parcelable接口 fragment.arguments = args return fragment } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 从arguments中取出参数 arguments?.let { parameterss = it.getParcelable(ARG_PARAM)!! } } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val dialog = super.onCreateDialog(savedInstanceState) // 原有逻辑不变,直接用parameterss变量即可 return dialog } }
修正后的MainActivity.kt
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 用newInstance创建Fragment,传入需要的参数 val fragmentB = FragmentB.newInstance(你的参数实例) fragmentB.show(supportFragmentManager, FragmentB.TAG) } }
补充注意事项
- 自定义参数类型如果不是基础类型,必须实现
Parcelable接口才能存入Bundle。 - 不要在Fragment的构造函数中添加任何参数,强制保留无参构造。
内容的提问来源于stack exchange,提问作者Anne
相关产品推荐
相关产品推荐

