- Android Jetpack開發(fā):原理解析與應(yīng)用實戰(zhàn)
- 黃林晴
- 872字
- 2022-07-05 09:43:57
2.3 使用Lifecycle解決實際項目中常見的問題
了解Lifecycle的基本使用之后,接著來看如何使用Lifecycle解決實際項目中常見的問題。
2.3.1 Dialog內(nèi)存泄漏問題分析
Dialog是Android開發(fā)中最常用的組件之一,相信每位讀者都使用過。現(xiàn)在一起實現(xiàn)一個Dialog,用于網(wǎng)絡(luò)請求的簡單提示。Dialog的代碼很簡單,直接設(shè)置一個布局即可,具體如下:
class TipDialog(context: Context) : Dialog(context) { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.item_tip_dialog) } }
接下來模擬如下場景:
- 進入頁面時開始網(wǎng)絡(luò)請求,顯示Dialog。
- 請求結(jié)束時(兩秒后),退出當(dāng)前頁面。
下面實現(xiàn)上述需求,Activity的代碼如下:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main2) TipDialog(this).show() Handler().postDelayed({ finish() }, 2000) } }
運行程序,兩秒后,軟件出現(xiàn)異常崩潰,錯誤日志如下:
00:58:23.618 28162-28162/com.example.jetpackdemo E/WindowManager: android.view.WindowLeaked: Activity com.example.jetpackdemo.ui.activity.MainActivity has leaked window DecorView@df7a4a4[MainActivity] that was originally added here at android.view.ViewRootImpl.<init>(ViewRootImpl.java:818) at android.view.ViewRootImpl.<init>(ViewRootImpl.java:798) at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:399) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:110) at android.app.Dialog.show(Dialog.java:353) at com.example.jetpackdemo.ui.activity.MainActivity.onCreate(MainActivity.kt:23) at android.app.Activity.performCreate(Activity.java:8146) at android.app.Activity.performCreate(Activity.java:8130) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1310) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3668) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3866) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:140) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:100) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2296) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:254) at android.app.ActivityThread.main(ActivityThread.java:8234) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1006)
相信很多開發(fā)者都遇到過這個錯誤,這是因為在Activity關(guān)閉的時候,Dialog沒有關(guān)閉,進而導(dǎo)致內(nèi)存泄漏。了解了出現(xiàn)異常的原因,解決起來就很容易了,在銷毀Activity的時候,關(guān)閉Dialog即可,示例代碼如下:
class MainActivity : AppCompatActivity() { var dialog: TipDialog? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main2) dialog = TipDialog(this) dialog?.show() Handler().postDelayed({ finish() }, 2000) } override fun onDestroy() { super.onDestroy() dialog?.dismiss() } }
上面的方法雖然可以解決內(nèi)存泄漏問題,但若彈窗類型很多,則需要在onDestroy中編寫許多額外的處理邏輯,且容易忘記,不過,如果使用Lifecycle組件,就可以完美地解決這個問題。
2.3.2 使用Lifecycle打造一個完美的Dialog
由于Dialog中的參數(shù)Context必須是Activity的上下文,因此開發(fā)者完全可以在Dialog中使用Lifecycle組件來感知生命周期,在2.2.1節(jié)中已經(jīng)介紹,只要是在androidx.fragment.app.Fragment、ComponentActivity及其子類Activity中,就可以直接使用Lifecycle組件。所以這成了一個取舍問題,如果xxxActivity繼承的是Activity,將無法直接使用Lifecycle,那就只能自定義LifecycleOwner或者在Activity中注冊了,但是這樣做完全沒有必要,這里默認xxxActivity繼承的是ComponentActivity。
修改TipDialog的代碼,使得TipDialog可以感應(yīng)生命周期變化,示例如下:
class TipDialog(context: Context) : Dialog(context), LifecycleObserver { init { if (context is ComponentActivity) { (context as ComponentActivity).lifecycle.addObserver(this) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.item_tip_dialog) } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) private fun onDestroy() { if (isShowing) { dismiss() } } }
上面的代碼在2.2.1節(jié)中已經(jīng)詳細介紹了,此處就不再贅述。當(dāng)Dialog所依附的Activity被銷毀時,Dialog也可以自動關(guān)閉,再也不用擔(dān)心Dialog的內(nèi)存泄漏問題了。如此一來,就使用Lifecycle實現(xiàn)了一個完美的Dialog。
注意
在實際項目開發(fā)中,Dialog使用不當(dāng)會出現(xiàn)除了內(nèi)存泄漏之外的其他問題,這需要開發(fā)者自行處理,這里解決的只是此種情境下產(chǎn)生的內(nèi)存泄漏問題。
- LabVIEW入門與實戰(zhàn)開發(fā)100例
- 架構(gòu)不再難(全5冊)
- Microsoft System Center Orchestrator 2012 R2 Essentials
- Bootstrap 4:Responsive Web Design
- Python完全自學(xué)教程
- 小學(xué)生C++創(chuàng)意編程(視頻教學(xué)版)
- C# Multithreaded and Parallel Programming
- Learning AWS
- Raspberry Pi Robotic Blueprints
- 深入分析GCC
- 超好玩的Scratch 3.5少兒編程
- Vue.js項目開發(fā)實戰(zhàn)
- 微軟辦公軟件認證考試MOS Access 2013實訓(xùn)教程
- Getting Started with Oracle WebLogic Server 12c:Developer’s Guide
- DevOps和自動化運維實踐