Olá! Hoje continuo falando sobre ferramentas que, por algum motivo, foram privadas de atenção. No meu artigo anterior , escrevi sobre as possibilidades de ActivityLifecycleCallbacks e como elas podem ser usadas nĂŁo apenas para registrar o ciclo de vida. Mas, alĂ©m de Activity, tambĂ©m há Fragment, e querĂamos obter um comportamento semelhante para eles.
Sem hesitar, abri uma pesquisa por classes no AndroidStudio (Cmd / Ctrl + O) e inseri FragmentLifecycleCallbacks lá. E qual foi a minha surpresa quando a pesquisa me mostrou FragmentManager.FragmentLifecycleCallbacks. Os leitores mais impacientes escreveram sobre isso nos comentários, então aqui está a continuação de toda a história. Pelo contrário, sob o corte!

O que Ă© isso
Uma interface como ActivityLifecycleCallbacks, apenas para 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()
)
}
}
?