你好!今天,我继续谈论由于某种原因被忽视的工具。在上一篇文章中,我写了关于ActivityLifecycleCallbacks的可能性以及如何将它们不仅用于记录生命周期的方法。但是除了Activity,还有Fragment,我们希望为其获得类似的行为。
我毫不犹豫地打开了AndroidStudio中的类搜索(Cmd / Ctrl + O),然后在其中输入FragmentLifecycleCallbacks。当搜索显示给我FragmentManager.FragmentLifecycleCallbacks时,我感到惊讶。最不耐烦的读者在评论中写了这个,所以这是整个故事的延续。相反,在削减!

这是什么
像ActivityLifecycleCallbacks这样的接口,仅适用于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()
)
}
}
?