(廢棄)簡(jiǎn)單的 applicappation 通用組件

開(kāi)場(chǎng)白

今天突然有感,想寫(xiě)一個(gè)通用的 application 組件出來(lái),應(yīng)該是對(duì) application 的思考和積累有點(diǎn)心得了,要不怎么會(huì)突然冒出這個(gè)想法呢

在項(xiàng)目中我們都會(huì)一個(gè) MainApplication 類承載我們 application 中的邏輯,期中有很大一部分邏輯代碼都是通用的,考慮到平臺(tái)化的問(wèn)題(我司內(nèi)部就有好幾個(gè) app),怎么復(fù)用 application 是個(gè)問(wèn)題。還有一部分功能和業(yè)務(wù)組件時(shí)需要 applicationContent 的,所以怎么跨 app 通用 application 是個(gè)問(wèn)題。


application 組件思路

application 抽象成公共組件是個(gè)必然,但是在 app 內(nèi)我們不能簡(jiǎn)單的復(fù)用 application 類型,每個(gè) app 中的application 都是不同的,所以難點(diǎn)在于怎么讓 application 可以實(shí)現(xiàn)跨 app 。

上面的問(wèn)題可以使用代理的思路,全局靜態(tài)的 applicationProxy 對(duì)象持有 app 的 application 對(duì)象,這樣統(tǒng)一了 application 類型,我們就能在任何地方使用 application 了。

另外添加了一些 application 常用的功能:

  • app 啟動(dòng),home 鍵切入后臺(tái),切回前臺(tái)的回調(diào)和狀態(tài)記錄
  • 手機(jī)信息采集
  • 棧管理(類我聲明了,具體邏輯沒(méi)寫(xiě))
  • app 進(jìn)程回收優(yōu)化

application 組件分層

因?yàn)橐獙?shí)現(xiàn)的功能不多,我也不打算寫(xiě)多少,所以 application 組件功能分層很簡(jiǎn)單,有下面幾個(gè)類:

  • ApplicationComponent
    application 組件外部公共入口
  • AppStateManage
    app 狀態(tài)記錄器,有4個(gè)標(biāo)記位:app 啟動(dòng),進(jìn)入后臺(tái),進(jìn)入前臺(tái),當(dāng)前狀態(tài)
  • ActivityManage
    app activity 棧管理
  • PhoneInfoManage
    手機(jī)信息采集器
  • ListenerAdapter
    回調(diào)適配器
AppStateManage

AppStateManage 定義的4個(gè) app 狀態(tài)值需要搞清楚

    // app 首次啟動(dòng)
    public static final int STATE_APPSTATE = 0;
    // app 在前臺(tái)
    public static final int STATE_FRONT = 1;
    // app 在后臺(tái)
    public static final int STATE_BACKGROUD = -1;
    // app 當(dāng)前狀態(tài)
    public int currentState = STATE_APPSTATE;
ApplicationComponent
public class ApplicationComponent {

    ..............

    public void attach(Application application) {

        if (application != null) {
            this.application = application;
            initParameter();
            registerActivityLifecycleCallback();
        }
    }
 }

ApplicationComponent 因?yàn)橐獙?duì)外提供統(tǒng)一的公共入口,所以靜態(tài)單例是沒(méi)跑了

ApplicationComponent 核心就是 attach 方法,attach 方法會(huì)關(guān)聯(lián) app 的 application 對(duì)象并給 application 對(duì)象注冊(cè) ActivityLifecycleCallbacks 全局回調(diào)監(jiān)聽(tīng)函數(shù),Application 組件的核心功能都是在這里實(shí)現(xiàn)的

ActivityManage

ActivityManage 應(yīng)該是實(shí)現(xiàn) activity 棧管理的,我這里沒(méi)做。我在 ActivityManage 里面記錄了活動(dòng)窗口數(shù)量,這個(gè)參數(shù)是判斷 app 在后臺(tái)還是前臺(tái)的核心。


app 啟動(dòng),前臺(tái),后臺(tái)的判斷思路

這個(gè)需求大家應(yīng)該都碰到過(guò),但是 android API 對(duì)這個(gè)需求真是無(wú)能為力,需要自己想辦法,我在上一個(gè)項(xiàng)目的日志模塊碰到的這個(gè)需求,需要準(zhǔn)確區(qū)分 app 的啟動(dòng),切入后臺(tái),切回前臺(tái)。

我的思路很簡(jiǎn)單,就是利用 application 注冊(cè)的 ActivityLifecycleCallbacks 全局監(jiān)聽(tīng)函數(shù)中的 activityStart 和 activityStop 方法中記錄當(dāng)前活躍的窗口數(shù)。

  • AppStateManage 中的 currentState 默認(rèn)是 app 啟動(dòng)
  • activityStart 函數(shù):
    * 先判斷 currentState 是不是 app 啟動(dòng)標(biāo)記,是的話,執(zhí)行 app 啟動(dòng)的回調(diào)函數(shù),然后currentState 置為前臺(tái)標(biāo)記,然后活動(dòng)窗口數(shù)++,return
    * 若 currentState 不是 app 啟動(dòng)標(biāo)記,并且活動(dòng)窗口數(shù)為0的話,表示切回前臺(tái),然后活動(dòng)窗口數(shù)++,return
  • activityStop 函數(shù),活動(dòng)窗口數(shù)先 -- ,若活動(dòng)窗口數(shù)為0的話,app 就進(jìn)入后臺(tái)了。

用這個(gè)思路,判斷 app 是不是首次啟動(dòng),home 切入后臺(tái),切回前臺(tái)很準(zhǔn)確,并且把這端邏輯放在 applicappation 組件中,適合別的組件調(diào)用,尤其是在推送中判斷當(dāng)前 app 的狀態(tài)是個(gè)很好的做法。

另外我在 ActivityManage 中只記錄了活動(dòng)窗口數(shù),大家可以自行擴(kuò)展線管公共,比如有的組件需要獲取到當(dāng)前活動(dòng)的 activity 對(duì)象的,放到 ActivityManage 挺合適的。


APP 進(jìn)程優(yōu)化

這個(gè)是應(yīng)對(duì)一個(gè)問(wèn)題: 系統(tǒng)殺后臺(tái)的 app 進(jìn)程會(huì)緩存 activity 棧信息,再次由系統(tǒng)啟動(dòng) app 進(jìn)程的話,界面會(huì)直接來(lái)到上次的位置。

這就帶來(lái)一個(gè)問(wèn)題,我們?cè)?flashActivity 中會(huì)寫(xiě)很多啟動(dòng)邏輯和初始化操作,要是有 activity 棧緩存的話,就不會(huì)執(zhí)行正常的啟動(dòng)邏輯了,flashActivity 頁(yè)面就沒(méi)法執(zhí)行了,有次會(huì)帶來(lái)很多問(wèn)題,尤其是初始化方法沒(méi)有執(zhí)行造成的空指針。我們?cè)趯?xiě)日志模塊時(shí),因?yàn)樾枰x寫(xiě) SD 卡的權(quán)限,所以日志組件的初始化放到 flashActivity 里,結(jié)果就因?yàn)檫@個(gè) activity 棧緩存的問(wèn)題報(bào)了很多次空指針,教訓(xùn)??!

那么面對(duì)這個(gè)問(wèn)題怎么解決呢,就是在 app 處于后臺(tái)進(jìn)程,并且快被回收時(shí),不用等系統(tǒng)回收,咱們自己殺自己,這樣就沒(méi)有 activity 棧緩存的問(wèn)題了,app 啟動(dòng)邏輯永遠(yuǎn)都會(huì)按我們?cè)O(shè)計(jì)的走,對(duì)我們就沒(méi)有干擾了。

關(guān)于后臺(tái)進(jìn)程回收優(yōu)先級(jí)的點(diǎn)看我這篇文章:

關(guān)于殺進(jìn)程的問(wèn)題再補(bǔ)充一下,app 處于后臺(tái)時(shí)不管我們?cè)趺礆⑦M(jìn)程都沒(méi)事,但是 app 在前臺(tái)時(shí)我們殺進(jìn)程,進(jìn)程的確會(huì)被殺死,但是進(jìn)程在被殺死之后還會(huì)重啟,沒(méi)有 activity 棧緩存的問(wèn)題,會(huì)按正常邏輯啟動(dòng) app

殺進(jìn)程的方法如下:


最后

項(xiàng)目地址: BW_Application

完事之后,感覺(jué)寫(xiě)的很一般,太菜了,功能是分層了,但是邏輯沒(méi)有完全分層,尤其是對(duì) app 啟動(dòng),后太,前臺(tái)的邏輯判斷上,全都放在作為外部入口的 ApplicationComponent 類里了,這對(duì)不熟悉這個(gè)組件的朋友和未來(lái)的自己修改維護(hù)帶來(lái)了麻煩和困擾,一是邏輯位置不好找,二是不方便擴(kuò)展。引以為戒吧,從小處看代碼封裝的水平,代碼封裝的水平基本就代表了手底下的代碼編寫(xiě)水平,我這也是不合格呀。

大家就胡看吧,小白太菜沒(méi)辦法......

參考資料


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容