Skip to content

Commit 1c129bf

Browse files
authored
Merge pull request #69 from Petterpx/perf_lazy_install_lifecycle
perf:调整appLifecycle的安装时机
2 parents b9a4306 + 997f892 commit 1c129bf

14 files changed

Lines changed: 167 additions & 158 deletions

File tree

app/src/main/java/com/petterp/floatingx/app/MainActivity.kt

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,24 @@ class MainActivity : AppCompatActivity() {
4040
this.updateViewContent {
4141
it.setText(R.id.tvItemFx, "App")
4242
}
43-
}.show()
43+
}.show(this@MainActivity)
4444
}
4545
addItemView("更新当前[全局浮窗1]内容-(传递view方式)") {
46-
FloatingX.control(MultipleFxActivity.TAG_1).updateView {
47-
TextView(it).apply {
48-
layoutParams = ViewGroup.LayoutParams(
49-
ViewGroup.LayoutParams.WRAP_CONTENT,
50-
ViewGroup.LayoutParams.WRAP_CONTENT
51-
)
52-
text = "App"
53-
textSize = 15f
54-
setBackgroundColor(Color.GRAY)
55-
setPadding(10, 10, 10, 10)
46+
FloatingX.control(MultipleFxActivity.TAG_1).apply {
47+
updateView {
48+
TextView(it).apply {
49+
layoutParams = ViewGroup.LayoutParams(
50+
ViewGroup.LayoutParams.WRAP_CONTENT,
51+
ViewGroup.LayoutParams.WRAP_CONTENT
52+
)
53+
text = "App"
54+
textSize = 15f
55+
setBackgroundColor(Color.GRAY)
56+
setPadding(10, 10, 10, 10)
57+
}
5658
}
59+
show(this@MainActivity)
5760
}
58-
FloatingX.control(MultipleFxActivity.TAG_1).show()
5961
}
6062
addItemView("显示一个Activity悬浮窗-(展示与多指触摸)") {
6163
activityFx.show()

app/src/main/java/com/petterp/floatingx/app/MultipleFxActivity.kt

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,33 @@ class MultipleFxActivity : AppCompatActivity() {
1616
createLinearLayoutToParent {
1717
addNestedScrollView {
1818
addLinearLayout {
19-
addItemView("显示全局悬浮窗-tag1") {
19+
addItemView("显示全局悬浮窗(tag1)") {
2020
if (!FloatingX.isInstalled(TAG_1)) {
2121
CustomKtApplication.installTag1(application)
2222
}
23-
FloatingX.control(TAG_1).show()
23+
FloatingX.control(TAG_1).show(this@MultipleFxActivity)
2424
}
25-
addItemView("显示全局悬浮窗-tag2") {
25+
addItemView("显示全局悬浮窗(tag2)") {
2626
if (!FloatingX.isInstalled(TAG_2)) {
2727
CustomKtApplication.installTag2(application)
2828
}
29-
FloatingX.control(TAG_2).show()
29+
FloatingX.control(TAG_2).show(this@MultipleFxActivity)
3030
}
31-
addItemView("隐藏全局悬浮窗-tag1") {
32-
FloatingX.control(TAG_1).hide()
31+
addItemView("重复安装全局悬浮窗(tag1)") {
32+
CustomKtApplication.installTag1(application)
33+
FloatingX.control(TAG_1).show(this@MultipleFxActivity)
3334
}
34-
addItemView("隐藏全局悬浮窗-tag2") {
35-
FloatingX.control(TAG_2).hide()
35+
addItemView("隐藏全局悬浮窗(tag1)") {
36+
FloatingX.controlOrNull(TAG_1)?.hide()
37+
}
38+
addItemView("隐藏全局悬浮窗(tag2)") {
39+
FloatingX.controlOrNull(TAG_2)?.hide()
40+
}
41+
addItemView("关闭全局悬浮窗(tag1)") {
42+
FloatingX.controlOrNull(TAG_1)?.cancel()
43+
}
44+
addItemView("关闭全局悬浮窗(tag2)") {
45+
FloatingX.controlOrNull(TAG_2)?.cancel()
3646
}
3747
addItemView("卸载所有全局浮窗") {
3848
FloatingX.uninstallAll()

app/src/main/java/com/petterp/floatingx/app/kotlin/CustomKtApplication.kt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,18 @@ class CustomKtApplication : Application() {
2626
override fun onCreate() {
2727
super.onCreate()
2828

29-
FloatingX.install {
30-
setLayout(R.layout.item_floating)
31-
32-
// 如果你全局 [只需要一个浮窗],这里可以不用传递 tag,默认我们会使用 FX_DEFAULT_TAG 作为未传递TAG时的默认值
33-
// 这样的好处是,后续调用控制器(FloatingX.control())时,不用传递 tag。因为相应的方法默认参数里已经携带了该tag
34-
// 比如:FloatingX.control()、FloatingX.configControl()
35-
// 注意:如果你重复调用install()方法,且未设置tag,那么新的浮窗将会覆盖旧的默认浮窗
36-
37-
// 注意:这里的tag是用来区分不同的浮窗的,如果你需要多个浮窗,那么请务必设置不同的tag
38-
// 注意: 当你调用控制器时,必须传递对应的tag,否则将会抛出异常,除非你使用了 [可null] 的获取方法
39-
setTag("ONE")
40-
}
29+
// FloatingX.install {
30+
// setLayout(R.layout.item_floating)
31+
//
32+
// // 如果你全局 [只需要一个浮窗],这里可以不用传递 tag,默认我们会使用 FX_DEFAULT_TAG 作为未传递TAG时的默认值
33+
// // 这样的好处是,后续调用控制器(FloatingX.control())时,不用传递 tag。因为相应的方法默认参数里已经携带了该tag
34+
// // 比如:FloatingX.control()、FloatingX.configControl()
35+
// // 注意:如果你重复调用install()方法,且未设置tag,那么新的浮窗将会覆盖旧的默认浮窗
36+
//
37+
// // 注意:这里的tag是用来区分不同的浮窗的,如果你需要多个浮窗,那么请务必设置不同的tag
38+
// // 注意: 当你调用控制器时,必须传递对应的tag,否则将会抛出异常,除非你使用了 [可null] 的获取方法
39+
// setTag(MultipleFxActivity.TAG_1)
40+
// }
4141

4242
installTag1(this)
4343
}

floatingx/src/main/java/com/petterp/floatingx/FloatingX.kt

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.petterp.floatingx
22

33
import android.annotation.SuppressLint
4+
import android.app.Activity
45
import android.app.Application
56
import android.content.Context
67
import com.petterp.floatingx.assist.helper.AppHelper
@@ -14,8 +15,9 @@ import com.petterp.floatingx.util.FX_DEFAULT_TAG
1415
/** Single Control To Fx */
1516
@SuppressLint("StaticFieldLeak")
1617
object FloatingX {
17-
private lateinit var context: Context
18-
private var fxs = HashMap<String, FxAppControlImpl>(3)
18+
private lateinit var context: Application
19+
private const val DEFAULT_FXS_INITIAL_CAPACITY = 3
20+
private var fxs = HashMap<String, FxAppControlImpl>(DEFAULT_FXS_INITIAL_CAPACITY)
1921
private var fxLifecycleCallback: FxLifecycleCallbackImpl? = null
2022

2123
/**
@@ -28,7 +30,7 @@ object FloatingX {
2830
ReplaceWith("", "")
2931
)
3032
@JvmSynthetic
31-
fun init(obj: AppHelper.Builder.() -> Unit) = install(obj)
33+
inline fun init(obj: AppHelper.Builder.() -> Unit) = install(obj)
3234

3335
/**
3436
* 初始化全局悬浮窗
@@ -48,7 +50,8 @@ object FloatingX {
4850
* 方法含义见 [install(helper: AppHelper)]
4951
*/
5052
@JvmSynthetic
51-
fun install(obj: AppHelper.Builder.() -> Unit) = install(AppHelper.builder().apply(obj).build())
53+
inline fun install(obj: AppHelper.Builder.() -> Unit) =
54+
install(AppHelper.builder().apply(obj).build())
5255

5356
/**
5457
* 安装一个新的全局浮窗
@@ -59,9 +62,10 @@ object FloatingX {
5962
*/
6063
@JvmStatic
6164
fun install(helper: AppHelper): IFxAppControl {
62-
fxs[helper.tag]?.cancel()
65+
if (fxs.isNotEmpty()) fxs[helper.tag]?.cancel()
6366
val fxAppControlImpl = FxAppControlImpl(helper, FxProxyLifecycleCallBackImpl())
6467
fxs[helper.tag] = fxAppControlImpl
68+
if (helper.enableFx) checkAppLifecycleInstall()
6569
return fxAppControlImpl
6670
}
6771

@@ -110,6 +114,7 @@ object FloatingX {
110114
}
111115

112116
/** 判断该tag对应的全局浮窗是否存在 */
117+
@JvmStatic
113118
fun isInstalled(tag: String): Boolean {
114119
return fxs[tag] != null
115120
}
@@ -126,15 +131,8 @@ object FloatingX {
126131
}
127132

128133
@JvmSynthetic
129-
internal fun initAppLifecycle(context: Context) {
130-
this.context = context
131-
if (fxLifecycleCallback == null) {
132-
fxLifecycleCallback = FxLifecycleCallbackImpl()
133-
}
134-
(context as Application).apply {
135-
unregisterActivityLifecycleCallbacks(fxLifecycleCallback)
136-
registerActivityLifecycleCallbacks(fxLifecycleCallback)
137-
}
134+
internal fun initContext(context: Context) {
135+
this.context = context as Application
138136
}
139137

140138
@JvmSynthetic
@@ -144,12 +142,36 @@ object FloatingX {
144142
internal fun getContext(): Context = context
145143

146144
@JvmSynthetic
147-
internal fun reset(tag: String) {
148-
fxs.remove(tag)
145+
internal fun uninstall(tag: String, control: FxAppControlImpl) {
146+
if (fxs.values.contains(control)) fxs.remove(tag)
147+
// 如果全局浮窗为null,自动清空配置
148+
if (fxs.isEmpty()) {
149+
release()
150+
}
151+
}
152+
153+
/**
154+
* 检查AppLifecycle是否安装
155+
*
156+
* @param activity 初始化时的activity
157+
*/
158+
@JvmSynthetic
159+
internal fun checkAppLifecycleInstall(activity: Activity? = null) {
160+
if (fxLifecycleCallback != null) return
161+
FxLifecycleCallbackImpl.updateTopActivity(activity)
162+
fxLifecycleCallback = FxLifecycleCallbackImpl()
163+
context.registerActivityLifecycleCallbacks(fxLifecycleCallback)
149164
}
150165

151166
private fun getTagFxControl(tag: String): FxAppControlImpl {
152167
return fxs[tag]
153168
?: throw NullPointerException("fxs[$tag]==null!,Please check if FloatingX.install() or AppHelper.setTag() is called.")
154169
}
170+
171+
private fun release() {
172+
if (fxLifecycleCallback == null && FxLifecycleCallbackImpl.topActivity == null) return
173+
context.unregisterActivityLifecycleCallbacks(fxLifecycleCallback)
174+
FxLifecycleCallbackImpl.releaseTopActivity()
175+
fxLifecycleCallback = null
176+
}
155177
}

floatingx/src/main/java/com/petterp/floatingx/assist/helper/BasisHelper.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.petterp.floatingx.assist.helper
22

3-
import android.content.Context
43
import android.view.View
54
import android.widget.FrameLayout
65
import androidx.annotation.LayoutRes
@@ -111,8 +110,6 @@ open class BasisHelper {
111110
}
112111

113112
abstract class Builder<T, B : BasisHelper> {
114-
private var context: Context? = null
115-
116113
@LayoutRes
117114
private var layoutId: Int = 0
118115
private var layoutView: View? = null

floatingx/src/main/java/com/petterp/floatingx/assist/helper/ScopeHelper.kt

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,42 @@ import android.app.Activity
44
import android.widget.FrameLayout
55
import androidx.fragment.app.Fragment
66
import com.petterp.floatingx.impl.control.FxScopeControl
7-
import com.petterp.floatingx.listener.control.IFxControl
87
import com.petterp.floatingx.listener.control.IFxScopeControl
8+
import com.petterp.floatingx.util.FxScopeEnum
9+
import com.petterp.floatingx.util.contentView
910

1011
/** 特定范围的Helper构建器 */
1112
class ScopeHelper : BasisHelper() {
1213

1314
/** 插入到Activity中 */
14-
fun toControl(activity: Activity): IFxControl =
15-
toControl().init(activity)
15+
fun toControl(activity: Activity): IFxScopeControl<Activity> {
16+
initLog(FxScopeEnum.ACTIVITY_SCOPE.tag)
17+
val control = FxScopeControl<Activity>(this)
18+
activity.contentView?.let {
19+
control.setContainerGroup(it)
20+
} ?: fxLog?.e("install to Activity the Error,current contentView(R.id.content) = null!")
21+
return control
22+
}
1623

1724
/** 插入到Fragment中 */
18-
fun toControl(fragment: Fragment): IFxControl =
19-
toControl().init(fragment)
25+
fun toControl(fragment: Fragment): IFxScopeControl<Fragment> {
26+
initLog(FxScopeEnum.FRAGMENT_SCOPE.tag)
27+
val rootView = fragment.view as? FrameLayout
28+
checkNotNull(rootView) {
29+
"Check if your root layout is FrameLayout, or if the init call timing is after onCreateView()!"
30+
}
31+
val control = FxScopeControl<Fragment>(this)
32+
control.setContainerGroup(rootView)
33+
return control
34+
}
2035

2136
/** 插入到ViewGroup中 */
22-
fun toControl(group: FrameLayout): IFxControl =
23-
toControl().init(group)
24-
25-
private fun toControl(): IFxScopeControl<IFxControl> = FxScopeControl(this)
37+
fun toControl(group: FrameLayout): IFxScopeControl<FrameLayout> {
38+
initLog(FxScopeEnum.VIEW_GROUP_SCOPE.tag)
39+
val control = FxScopeControl<FrameLayout>(this)
40+
control.setContainerGroup(group)
41+
return control
42+
}
2643

2744
companion object {
2845
@JvmStatic

floatingx/src/main/java/com/petterp/floatingx/impl/control/FxAppControlImpl.kt

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,11 @@ class FxAppControlImpl(
3838
}
3939

4040
override fun show(activity: Activity) {
41-
super.show()
4241
if (isShow()) return
4342
if (attach(activity)) {
4443
getManagerView()?.show()
44+
updateEnableStatus(true)
45+
FloatingX.checkAppLifecycleInstall()
4546
}
4647
}
4748

@@ -68,16 +69,6 @@ class FxAppControlImpl(
6869

6970
override fun context(): Context = FloatingX.getContext()
7071

71-
/** 请注意: 调用此方法前请确定在初始化fx时,调用了show方法,否则,fx默认不会插入到全局Activity */
72-
override fun show() {
73-
if (topActivity == null) {
74-
helper.enableFx = true
75-
helper.fxLog?.e("show-fx, topActivity=null,Do not call it during initialization in Application!")
76-
return
77-
}
78-
show(topActivity!!)
79-
}
80-
8172
private fun initWindowsInsetsListener() {
8273
getManagerView()?.let {
8374
ViewCompat.setOnApplyWindowInsetsListener(it, windowsInsetsListener)
@@ -130,7 +121,7 @@ class FxAppControlImpl(
130121
// 重置之前记得移除insets
131122
clearWindowsInsetsListener()
132123
super.reset()
133-
FloatingX.reset(helper.tag)
124+
FloatingX.uninstall(helper.tag, this)
134125
}
135126

136127
private fun clearWindowsInsetsListener() {

floatingx/src/main/java/com/petterp/floatingx/impl/control/FxBasisControlImpl.kt

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,24 +32,18 @@ open class FxBasisControlImpl(private val helper: BasisHelper) : IFxControl, IFx
3232
* */
3333
override val configControl: IFxConfigControl get() = this
3434

35-
override fun show() {
36-
if (!helper.enableFx) helper.enableFx = true
37-
}
38-
3935
override fun cancel() {
40-
if (managerView == null && viewHolder == null) return
41-
if (helper.enableAnimation &&
42-
helper.fxAnimation != null
43-
) {
36+
if ((managerView == null && viewHolder == null)) return
37+
if (isShow() && helper.enableAnimation && helper.fxAnimation != null) {
4438
managerView?.removeCallbacks(cancelAnimationRunnable)
4539
val duration = helper.fxAnimation!!.toEndAnimator(managerView)
4640
animatorCallback(duration, cancelAnimationRunnable)
4741
} else reset()
4842
}
4943

5044
override fun hide() {
51-
if (helper.enableFx) helper.enableFx = false
5245
if (!isShow()) return
46+
updateEnableStatus(false)
5347
if (helper.enableAnimation && helper.fxAnimation != null) {
5448
if (helper.fxAnimation!!.endJobIsRunning()) {
5549
helper.fxLog?.d("fxView->Animation ,endAnimation Executing, cancel this operation!")
@@ -215,10 +209,6 @@ open class FxBasisControlImpl(private val helper: BasisHelper) : IFxControl, IFx
215209
return mContainer?.get()
216210
}
217211

218-
protected fun setContainerGroup(viewGroup: ViewGroup) {
219-
mContainer = WeakReference(viewGroup)
220-
}
221-
222212
protected open fun detach(container: ViewGroup?) {
223213
if (managerView != null && container != null) {
224214
helper.fxLog?.d("fxView-lifecycle-> code->removeView")
@@ -259,6 +249,7 @@ open class FxBasisControlImpl(private val helper: BasisHelper) : IFxControl, IFx
259249
}
260250
}
261251

252+
@JvmSynthetic
262253
protected open fun reset() {
263254
managerView?.removeCallbacks(hideAnimationRunnable)
264255
managerView?.removeCallbacks(cancelAnimationRunnable)
@@ -269,4 +260,14 @@ open class FxBasisControlImpl(private val helper: BasisHelper) : IFxControl, IFx
269260
clearContainer()
270261
helper.fxLog?.d("fxView-lifecycle-> code->cancelFx")
271262
}
263+
264+
/** 更新启用状态 */
265+
protected fun updateEnableStatus(newStatus: Boolean) {
266+
if (helper.enableFx == newStatus) return
267+
helper.enableFx = newStatus
268+
}
269+
270+
internal fun setContainerGroup(viewGroup: ViewGroup) {
271+
mContainer = WeakReference(viewGroup)
272+
}
272273
}

0 commit comments

Comments
 (0)