Kotlin入門(28)Application單例化

来源:https://www.cnblogs.com/aqi00/archive/2018/10/23/9837936.html
-Advertisement-
Play Games

Application是Android的又一大組件,在App運行過程中,有且僅有一個Application對象貫穿應用的整個生命周期,所以適合在Application中保存應用運行時的全局變數。而開展該工作的基礎,是必須獲得Application對象的唯一實例,也就是將Application單例化。 ...


Application是Android的又一大組件,在App運行過程中,有且僅有一個Application對象貫穿應用的整個生命周期,所以適合在Application中保存應用運行時的全局變數。而開展該工作的基礎,是必須獲得Application對象的唯一實例,也就是將Application單例化。獲取一個類的單例對象,需要運用程式設計中常見的單例模式,倘若通過Java編碼實現單例化,想必早已是大家耳熟能詳的了。下麵便是個Application單例化的Java代碼例子:

public class MainApplication extends Application {

    private static MainApplication mApp;
    
    public static MainApplication getInstance() {
        return mApp;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mApp = this;
    }
}

從上可見這個單例模式的實現過程主要有三個步驟,說明如下:

1、在自定義的Application類內部聲明一個該類的靜態實例;
2、重寫onCreate方法,把自身對象賦值給第一步聲明的實例;
3、提供一個供外部調用的靜態方法getInstance,該方法返回第一步聲明的Application類實例;
不管是代碼還是步驟,這個單例化的實現都還蠻簡單的。同樣的單例化過程通過Kotlin編碼實現的話,靜態屬性和靜態方法可利用伴生對象來實現,這樣就形成了Kotlin單例化的第一種方式:手工聲明屬性的單例化,具體描述見下。


一、手工聲明屬性的單例化
該方式與Java的常見做法一致,也是手工聲明自身類的靜態實例,然後通過靜態方法返回自身實例。與Java的不同之處在於:Kotlin引入了空安全機制,故而靜態屬性要聲明為可空變數、然後獲得實例時要在末尾加上雙感嘆號表示非空,當然也可事先將自身實例聲明為延遲初始化屬性。總之,兩種聲明手段都是為了確保一個目的,即Application類提供給外部訪問的自身實例必須是非空的。
下麵是手工單例化的Kotlin代碼例子:

class MainApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        instance = this
    }

    //單例化的第一種方式:聲明一個簡單的Application屬性
    companion object {
        //情況一:聲明可空的屬性
        private var instance: MainApplication? = null
        fun instance() = instance!!
        //情況二:聲明延遲初始化屬性
        //private lateinit var instance: MainApplication
        //fun instance() = instance
    }
}

  

二、藉助Delegates的委托屬性單例化
第一種方式的單例化,雖然提供了兩種屬性的聲明手段,但只是為了保證自身實例的非空性。如果僅僅是確保屬性非空,其實Kotlin已經提供了一個系統工具進行自動校驗,這個工具便是Delegates的notNull方法。該方法返回非空校驗的行為,只要將指定屬性的讀寫行為委托給這個非空校驗行為,那麼開發者就無需手工進行非空判斷了。利用Delegates工具的屬性代理功能,就構成了Kotlin的第二種單例化方式;有關委托屬性和屬性代理的介紹,可參見前面的博文《Kotlin入門(25)共用參數模板》。
下麵是系統委托屬性單例化的Kotlin代碼例子:

class MainApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        instance = this
    }

    //單例化的第二種方式:利用系統自帶的Delegates生成委托屬性
    companion object {
        private var instance: MainApplication by Delegates.notNull()
        fun instance() = instance
    }
}

第二種方式的委托屬性單例化,在App代碼中獲取Application實例與第一種方式是一樣的,都是調用“MainApplication.instance()”這個函數獲得Application的自身實例。

三、自定義委托行為的單例化
前兩種單例化都只完成了非空校驗,還不是嚴格意義上的單例化。真正的單例化是有且僅有一次賦值操作,儘管前兩種的單例化並未實現唯一賦值功能,但是在大多數場合已經夠用了。可是作為孜孜不倦的開發者,務必要究根問底,到底能不能實現唯一賦值情況下的單例化。顯然系統自帶的Delegates工具沒有提供大家期待的校驗行為,於是開發者必須自己寫一個能夠校驗賦值次數的行為類,目的是接管委托屬性的讀寫行為。自定義接管行為的實現,前面的博文《Kotlin入門(25)共用參數模板》即已給出了Preference<T>的完整源碼,其中關鍵是重寫了讀方法getValue和寫方法setValue,因此在這裡可借鑒Preference<T>完成自定義的委托行為編碼。
下麵是自定義委托行為的單例化代碼:

class MainApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        instance = this
    }

    //單例化的第三種方式:自定義一個非空且只能一次性賦值的委托屬性
    companion object {
        private var instance: MainApplication by NotNullSingleValueVar()
        fun instance() = instance
    }

    //定義一個屬性管理類,進行非空和重覆賦值的判斷
    private class NotNullSingleValueVar<T>() : ReadWriteProperty<Any?, T> {
        private var value: T? = null
        override fun getValue(thisRef: Any?, property: KProperty<*>): T {
            return value ?: throw IllegalStateException("application not initialized")
        }

        override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
            this.value = if (this.value == null) value
            else throw IllegalStateException("application already initialized")
        }
    }
}

由上述代碼看到,自定義的委托行為在getValue方法中進行非空校驗,在setValue方法中進行重覆賦值的校驗,從而按照要求接管了委托屬性的讀寫行為。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 筆者在看了相關的教程之後發現教程當中的資源已經過時了。當我們在創建了一個新的空白的工程之後,會發現其文件夾下麵的分文件夾目錄和官方的教程文件結構完全不同,因此會引起很多誤解。筆者使用的是最新版的Android Stuidio,其目錄結構如下圖所示: 一.創建主活動(First活動) 從中我們可以得到 ...
  • 一,首先,我們在菜單欄上找到這一欄: 然後點擊build,再點擊generate apk,然後出現以下界面: 由於之前我們並沒有進行apk文件的生成,因此需要這個apk key做一個驗證,以防您的app上線之後被別人盜用,同時證明自己對這個app的擁有權。key store path就是您app k ...
  • Android json支持五種數據類型 String / int(float)/bool / null / object 今天說 object : ...
  • 歡迎大家前往 "騰訊雲+社區" ,獲取更多騰訊海量技術實踐乾貨哦~ 本文由 "elson" 發表於 "雲+社區專欄" 目前在不考慮IE以及低端安卓機(4.3 )的相容下,已經可以放心使用flex進行佈局了。什麼是flex佈局以及它的好處,這裡就不再贅述。 在這篇文章里,想說說flex佈局的屬性語法及 ...
  • 準備 工具:HBuilder 一、全屏設置,不顯示系統狀態欄 這裡所說的系統狀態欄就是包括了:信號、運營商、電量等信息手機屏幕最頂部信息。 全屏並非狀態欄透明或變色,而是沒有狀態欄,也就是看不見電量、信號那條了,部分項目需要這樣的場景。 全屏設置方法: 新建一個wap2app項目並完成各項配置後,打 ...
  • Android預設的Toast太醜了,我們來封裝一個花里胡哨的Toast吧,就叫ColoredToast。 Github:https://github.com/imcloudfloating/DesignApp 效果: Toast有一個setView方法,通過它我們可以設置自定義的佈局,這裡我只是加 ...
  • C/S架構(Client/Server,即客戶機/伺服器模式)分為客戶機和伺服器兩層:第一層是在客戶機系統上結合了表示與業務邏輯,第二層是通過網路結合了資料庫伺服器。簡單的說就是第一層是用戶表示層,第二層是資料庫層。客戶端和伺服器直接相連,這兩個組成部分都承擔著重要的角色。 Android內核是基於 ...
  • 前面已經封裝了很多常用、基礎的組件了: "base module" , 包括了: crash 處理 常用工具類 apk 升級處理 log 組件 logcat 採集 ftp 文件上傳 blur 高斯模糊 fresco 圖片處理 等等 那麼,今天繼續再來封裝一個網路組件,基於 "volley" 的二次封 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...