Create fragments

The wrong sample

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    supportFragmentManager.beginTransaction()
        .replace(R.id.container, NewFragment())
        .commit()
}
Copy the code

The problem

In the above code, when the Activity is destroyed and restored, a new Fragment is created.

The correct sample

We should use savedInstanceState == null.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    if (savedInstanceState == null) {           
        supportFragmentManager.beginTransaction()
            .replace(R.id.container, NewFragment())
            .commit()
    }
}
Copy the code

Create all objects of the Fragment in onCreateView

The wrong sample

private var presenter: MyPresenter? = null
override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup? , savedInstanceState: Bundle?) : View? { presenter = MyPresenter()return inflater.inflate(R.layout.frag_layout, container, false)}Copy the code

The problem

When the Fragment is replaced by a Fragment in another container, the Fragment is not destroyed. The data object in the Fragment is still there. When the Fragment is restored, onCreateView is called again and the data in the Fragment is reset.

The correct sample

We should create all the Fragment data objects in onCreate.

private var presenter: MyPresenter? = null
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    presenter = MyPresenter()
}
Copy the code

Save the Fragment in the Activity

The wrong sample

Sometimes, we save the Fragment in the Activity so that we can call the methods in the Fragment.

private var myFragment: MyFragment? = null
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    if (savedInstanceState == null) {  
        myFragment = NewFragment()
        supportFragmentManager.beginTransaction()
            .replace(R.id.container, myFragment)
            .commit()
    }
}
private fun anotherFunction(){ myFragemnt? .doSomething() }Copy the code

The problem

The Fragment has a lifetime, it is destroyed by the system, and the reference in the Activity does not exist. We need to make sure that the correct reference to the Fragment is constantly updated.

The correct sample

Use findFragmentByTag.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    if (savedInstanceState == null) {            
        supportFragmentManager.beginTransaction()
            .replace(R.id.container, NewFragment(), FragmentTag)
            .commit()
    }
}
private fun anotherFunction() {
    (supportFragmentManager.findFragmentByTag(FragmentTag) as? NewFragment)? .doSomething() }Copy the code

Use the simple class name as the TAG for the Fragment

The wrong sample

supportFragmentManager.beginTransaction()
    .replace(
        R.id.container, 
        fragment, 
        fragment.javaClass.simpleName)
    .commit()
Copy the code

The problem

In Android, we use Proguard or DexGuard to obscure class names. Along the way, obscure simple names can conflict with other class names.

The danger of using getSimpleName() as TAG for Fragment

The correct sample

supportFragmentManager.beginTransaction()
    .replace(
        R.id.container, 
        fragment, 
        fragment.javaClass.canonicalName)
    .commit()
Copy the code

reference

7 Common Mistakes Easily Made with Android Fragment