salut! Aujourd'hui, je continue de parler d'outils qui, pour une raison quelconque, ont été privés d'attention. Dans mon article précédent, j'ai écrit sur les possibilités de ActivityLifecycleCallbacks et comment ils peuvent être utilisés non seulement pour enregistrer le cycle de vie. Mais en plus d'Activité, il y a aussi Fragment, et nous voulions obtenir un comportement similaire pour eux.
Sans hésitation, j'ai ouvert la recherche de classes dans AndroidStudio (Cmd / Ctrl + O) et y ai entré FragmentLifecycleCallbacks. Et quelle a été ma surprise lorsque la recherche m'a montré FragmentManager.FragmentLifecycleCallbacks. Les lecteurs les plus impatients ont écrit à ce sujet dans les commentaires, voici donc la suite de toute cette histoire. Plutôt, sous la coupe!

Ce que c'est
Une interface comme ActivityLifecycleCallbacks, uniquement pour Fragment.
FragmentLifecycleCallbacks
public abstract static class FragmentLifecycleCallbacks {
public void onFragmentPreAttached(
@NonNull FragmentManager fm,
@NonNull Fragment f,
@NonNull Context context) {}
public void onFragmentAttached(
@NonNull FragmentManager fm,
@NonNull Fragment f,
@NonNull Context context) {}
public void onFragmentPreCreated(
@NonNull FragmentManager fm,
@NonNull Fragment f,
@Nullable Bundle savedInstanceState) {}
public void onFragmentCreated(
@NonNull FragmentManager fm,
@NonNull Fragment f,
@Nullable Bundle savedInstanceState) {}
public void onFragmentActivityCreated(
@NonNull FragmentManager fm,
@NonNull Fragment f,
@Nullable Bundle savedInstanceState) {}
public void onFragmentViewCreated(
@NonNull FragmentManager fm,
@NonNull Fragment f,
@NonNull View v,
@Nullable Bundle savedInstanceState) {}
public void onFragmentStarted(
@NonNull FragmentManager fm,
@NonNull Fragment f) {}
public void onFragmentResumed(
@NonNull FragmentManager fm,
@NonNull Fragment f) {}
public void onFragmentPaused(
@NonNull FragmentManager fm,
@NonNull Fragment f) {}
public void onFragmentStopped(
@NonNull FragmentManager fm,
@NonNull Fragment f) {}
public void onFragmentSaveInstanceState(
@NonNull FragmentManager fm,
@NonNull Fragment f,
@NonNull Bundle outState) {}
public void onFragmentViewDestroyed(
@NonNull FragmentManager fm,
@NonNull Fragment f) {}
public void onFragmentDestroyed(
@NonNull FragmentManager fm,
@NonNull Fragment f) {}
public void onFragmentDetached(
@NonNull FragmentManager fm,
@NonNull Fragment f) {}
}
ActivityLifecycleCallbacks Fragment, FragmentManager, . , Pre-, Fragment. , Fragment.
FragmentLifecycleCallbacks — , . , , .
— .
FragmentLifecycleCallbacks , FragmentManager. FragmentManager.registerFragmentLifecycleCallback(), : callback — recursive. , callback FragmentManager childFragmentManager’, FragmentManager' .

FragmentLifecycleCallback Activity.onCreate(), , , .
class FlcExampleActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
supportFragmentManager
.registerFragmentLifecycleCallbacks(
ExampleFragmentLifecycleCallback(),
true
)
super.onCreate(savedInstanceState)
}
}
class ExampleFragmentLifecycleCallback : FragmentManager.FragmentLifecycleCallbacks()
, - Activity. ActivityLifecycleCallbacks, , Activity =).
class ActivityFragmentLifecycleCallbacks :
Application.ActivityLifecycleCallbacks,
FragmentManager.FragmentLifecycleCallbacks() {
override fun onActivityCreated(
activity: Activity,
savedInstanceState: Bundle?
) {
(activity as? FragmentActivity)
?.supportFragmentManager
?.registerFragmentLifecycleCallbacks(this, true)
}
}
callback’. Activity Fragment, . , , .
dependency injection: , , Single Activity Application. , RequireCoolTool? Activity Fragment . , ? - .
Dependency injectioninterface CoolTool {
val extraInfo: String
}
class CoolToolImpl : CoolTool {
override val extraInfo = "i am dependency"
}
interface RequireCoolTool {
var coolTool: CoolTool
}
class InjectingLifecycleCallbacks :
Application.ActivityLifecycleCallbacks,
FragmentManager.FragmentLifecycleCallbacks() {
private val coolToolImpl = CoolToolImpl()
override fun onActivityCreated(
activity: Activity,
savedInstanceState: Bundle?
) {
(activity as? RequireCoolTool)?.coolTool = coolToolImpl
(activity as? FragmentActivity)
?.supportFragmentManager
?.registerFragmentLifecycleCallbacks(this, true)
}
override fun onFragmentPreCreated(
fm: FragmentManager,
f: Fragment,
savedInstanceState: Bundle?
) {
(f as? RequireCoolTool)?.coolTool = coolToolImpl
}
}
class DIActivity : AppCompatActivity(), RequireCoolTool {
override lateinit var coolTool: CoolTool
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(LinearLayout {
orientation = LinearLayout.VERTICAL
FrameLayout {
layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, 0, 1f)
Text(
"""
DI example activity
CoolTool.extraInfo="${coolTool.extraInfo}"
""".trimIndent()
)
}
FrameLayout {
layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, 0, 1f)
id = R.id.container
}
})
supportFragmentManager.findFragmentById(R.id.container) ?: run {
supportFragmentManager
.beginTransaction()
.add(R.id.container, DIFragment())
.commit()
}
}
}
class DIFragment : Fragment(), RequireCoolTool {
override lateinit var coolTool: CoolTool
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? =
inflater.context.FrameLayout {
setBackgroundColor(Color.LTGRAY)
Text(
"""
DI example fragment
CoolTool.extraInfo="${coolTool.extraInfo}"
""".trimIndent()
)
}
}
Dagger’ .
Daggerinterface DaggerTool {
val extraInfo: String
}
class DaggerToolImpl : DaggerTool {
override val extraInfo = "i am dependency"
}
class DaggerInjectingLifecycleCallbacks(
val dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
) : Application.ActivityLifecycleCallbacks,
FragmentManager.FragmentLifecycleCallbacks() {
override fun onActivityCreated(
activity: Activity,
savedInstanceState: Bundle?
) {
dispatchingAndroidInjector.maybeInject(activity)
(activity as? FragmentActivity)
?.supportFragmentManager
?.registerFragmentLifecycleCallbacks(this, true)
}
override fun onFragmentPreCreated(
fm: FragmentManager,
f: Fragment,
savedInstanceState: Bundle?
) {
dispatchingAndroidInjector.maybeInject(f)
}
}
class DaggerActivity : AppCompatActivity() {
@Inject
lateinit var daggerTool: DaggerTool
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(LinearLayout {
orientation = LinearLayout.VERTICAL
FrameLayout {
layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, 0, 1f)
Text(
"""
Dagger example activity
CoolTool.extraInfo="${daggerTool.extraInfo}"
""".trimIndent()
)
}
FrameLayout {
layoutParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, 0, 1f)
id = R.id.container
}
})
supportFragmentManager.findFragmentById(R.id.container) ?: run {
supportFragmentManager
.beginTransaction()
.add(R.id.container, DIFragment())
.commit()
}
}
}
class DaggerFragment : Fragment() {
@Inject
lateinit var daggerTool: DaggerTool
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? =
inflater.context.FrameLayout {
Text(
"""
Dagger example fragment
DaggerTool.extraInfo="${daggerTool.extraInfo}"
""".trimIndent()
)
}
}
@Module
class DaggerModule {
@Provides
fun provideDaggerTool(): DaggerTool {
return DaggerToolImpl()
}
}
@Module
abstract class DaggerAndroidModule {
@ContributesAndroidInjector(modules = [DaggerModule::class])
abstract fun contributeDaggerActivity(): DaggerActivity
@ContributesAndroidInjector(modules = [DaggerModule::class])
abstract fun contributeDaggerFragment(): DaggerFragment
}
, DI-, , .
, , Activity, , .
Analyticsinterface Screen {
val screenName: String
}
interface ScreenWithParameters : Screen {
val parameters: Map<String, String>
}
class AnalyticsCallback(
val sendAnalytics: (String, Map<String, String>?) -> Unit
) : Application.ActivityLifecycleCallbacks,
FragmentManager.FragmentLifecycleCallbacks() {
override fun onActivityCreated(
activity: Activity,
savedInstanceState: Bundle?
) {
if (savedInstanceState == null) {
(activity as? Screen)?.screenName?.let {
sendAnalytics(
it,
(activity as? ScreenWithParameters)?.parameters
)
}
}
}
}
class AnalyticsActivity : AppCompatActivity(), ScreenWithParameters {
override val screenName: String = "First screen"
override val parameters: Map<String, String> = mapOf("key" to "value")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(LinearLayout {
orientation = android.widget.LinearLayout.VERTICAL
FrameLayout {
layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, 0, 1f)
Text(
"""
Analytics example
see output in Logcat by "Analytics" tag
""".trimIndent()
)
}
FrameLayout {
layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, 0, 1f)
id = R.id.container
}
})
with(supportFragmentManager) {
findFragmentById(R.id.container) ?: commit {
add(R.id.container, AnalyticsFragment())
}
}
}
}
class AnalyticsFragment : Fragment(), ScreenWithParameters {
override val screenName: String = "Fragment screen"
override val parameters: Map<String, String> = mapOf("key" to "value")
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? =
inflater.context.FrameLayout {
setBackgroundColor(Color.LTGRAY)
Text(
"""
Analytics example
see output in Logcat by "Analytics" tag
""".trimIndent()
)
}
}
?