0

Which base fragment prefer to use and why? In this implementation layoutRes is abstract field.

abstract class BaseFragment1 : Fragment() {

    abstract val layoutRes: Int

    override fun onCreateView(inflater: LayoutInflater, 
                              container: ViewGroup?, 
                              savedInstanceState: Bundle?
            ): View {
        return inflater.inflate(layoutRes, container, false)
    }
}

And in this implementation layoutRes is passing through constructor

abstract class BaseFragment2(@LayoutRes private val layoutRes: Int) : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, 
                              container: ViewGroup?, 
                              savedInstanceState: Bundle?
        ): View {
            return inflater.inflate(layoutRes, container, false)
     }
}

I want to know which implementation is better to use? If you have another solution you can share it. Example of implementations:

class FramgnetA : BaseFragment1() {
    override val layuotRes = R.layout.layout
}

class FragmentB : BaseFragment2(R.layout.layout)
Axbor Axrorov
  • 2,720
  • 2
  • 17
  • 35
  • I don't think 2nd one will compile / would work at runtime. – Rahul Sep 25 '18 at 11:05
  • @RahulKumar Both of these implementations will work. Question is another ) – Axbor Axrorov Sep 25 '18 at 11:11
  • this is what I am talking about https://developer.android.com/reference/android/support/v4/app/Fragment.html#Fragment() "Every fragment must have an empty constructor, so it can be instantiated when restoring its activity's state. It is strongly recommended that subclasses do not have other constructors with parameters, since these constructors will not be called when the fragment is re-instantiated" – Rahul Sep 25 '18 at 11:18
  • @RahulKumar please look at question, I've edited it. – Axbor Axrorov Sep 25 '18 at 11:21
  • imo first one is more cleaner as you would be calling Fragments default constructor from your abstract Fragment. It would be very confusing when all the default constructors do not call their supers' default constructor. – Rahul Sep 25 '18 at 11:30
  • @RahulKumar but in most cases calling default constructor -> calling constructor with param with default value ) – Axbor Axrorov Sep 25 '18 at 11:36
  • @zapl Look careful... – Axbor Axrorov Sep 25 '18 at 16:43
  • ohhh, yes, ok, that's a valid schema for #2 - I guess whatever is less to write or looks better to you wins. – zapl Sep 25 '18 at 16:44

2 Answers2

2

Like in Best practice for instantiating a new Android Fragment - for parameters that can be supplied from the outside you can use a Bundle and Fragment#setArguments(Bundle)

E.g.

class DynamicContentFragment : Fragment() {
    companion object {
        private const val KEY_LAYOUT_ID = "layoutId"
        fun instance(@LayoutRes layoutRes: Int) =
                DynamicContentFragment().apply {
                    arguments = Bundle().apply { putInt(KEY_LAYOUT_ID, layoutRes) }
                }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        val layout = arguments!!.getInt(KEY_LAYOUT_ID)!!
        return inflater.inflate(layout, container, false)
    }
}

class UseCase {
    fun test(fm: FragmentManager) {
        fm.beginTransaction()
                .replace(R.id.container, DynamicContentFragment.instance(R.layout.main))
    }
}

Otherwise your solutions are fine but it require a new class per parameter. Classes are cheap to write in kotlin so it's preference I guess.

zapl
  • 63,179
  • 10
  • 123
  • 154
0

enter image description here

Recently google added this overload of the fragment constructors. I think now, everything very obvious.

Axbor Axrorov
  • 2,720
  • 2
  • 17
  • 35