# 內(nèi)存優(yōu)化
# 1. 合理使用分包加載
使用分包加載不僅能優(yōu)化啟動耗時,也能夠?qū)崿F(xiàn)頁面、組件和邏輯較粗粒度的按需加載,從而降低內(nèi)存的占用。詳情請參考《啟動優(yōu)化-代碼包體積優(yōu)化》
# 2. 使用按需注入和用時注入
通過開啟「按需注入」和「用時注入」,可以在運行時避免加載未使用到的頁面和組件,降低運行時的內(nèi)存占用。詳情請參考《啟動優(yōu)化-代碼注入優(yōu)化》
# 3. 內(nèi)存分析
如果要更精細的分析小程序邏輯層的內(nèi)存分布情況,可以使用開發(fā)者工具調(diào)試器的「內(nèi)存調(diào)試」或「真機調(diào)試 2.0」提供的「內(nèi)存調(diào)試」能力。
# 4. 處理內(nèi)存告警
當(dāng)小程序占用系統(tǒng)資源過高,可能會被系統(tǒng)銷毀或被微信客戶端主動回收。在 iOS 上,當(dāng)微信客戶端在一定時間間隔內(nèi)連續(xù)收到系統(tǒng)內(nèi)存告警時,會根據(jù)一定的策略,主動銷毀小程序,并提示用戶「運行內(nèi)存不足,請重新打開該小程序」。
建議小程序在必要時使用 wx.onMemoryWarning 監(jiān)聽內(nèi)存告警事件,進行必要的內(nèi)存清理。例如:釋放一些暫時不用的組件或 JS 對象。
# 5. 小程序常見的內(nèi)存泄露問題
存在內(nèi)存泄露問題會導(dǎo)致小程序在運行過程中內(nèi)存占用持續(xù)增長,引起小程序閃退或被被微信強制銷毀。
# 5.1 小程序長期持有頁面實例,導(dǎo)致頁面實例和引用的組件無法正常銷毀
頁面 unload 之后,基礎(chǔ)庫會從頁面棧中將頁面實例清理。正常情況下,JS 垃圾回收機制會將頁面進行回收,釋放內(nèi)存。
但如果開發(fā)者代碼中持有的頁面實例(this)未釋放,則會導(dǎo)致頁面未被正?;厥眨饍?nèi)存泄露。建議開發(fā)者注意,并在 unload 中進行必要的清理。
案例一:頁面實例被未解綁的事件監(jiān)聽引用
事件監(jiān)聽器中持有了頁面的 this,如果頁面銷毀后監(jiān)聽未解綁,會導(dǎo)致頁面無法釋放。
Page({
themeChangeHandler({ theme }) {
this.setData({ theme })
},
onLoad() {
this._handler = this.themeChangeHandler.bind(this)
wx.onThemeChange(this._handler)
},
// 修復(fù)方法:unload 中解綁監(jiān)聽
// onUnload() {
// wx.offThemeChange(this._handler)
// },
})
案例二:頁面實例被頁面外變量或全局變量引用
函數(shù)閉包內(nèi)持有了頁面的 this,且函數(shù)被掛到全局或頁面聲明周期外的變量,會導(dǎo)致頁面無法釋放。
let languageListener = null
Page({
onLoad() {
getApp().userInfoChangeListener = ({ userName }) => {
this.setData({ userName })
}
languageListener = ({ lang }) => {
this.setData({ lang })
}
},
// 修復(fù)方法:unload 中進行清理
// onUnload() {
// getApp().userInfoChangeListener = null
// languageListener = null
// },
})
案例三:頁面實例被異步回調(diào)長時間引用
如果在長時間未返回的異步回調(diào)中訪問了頁面的 this,如持續(xù)時間過長的 setTimeout、setInterval,耗時較長的 wx API 回調(diào)(如長時間的 wx.request 等),會導(dǎo)致頁面無法釋放。
Page({
onLoad() {
this._timer = setInterval(() => {
this.setData({
timerValue: Date.now()
})
}, 1000)
},
// 修復(fù)方法:unload 中進行清理
// onUnload() {
// clearInterval(this._timer)
// },
})
# 5.2 事件監(jiān)聽未及時解綁
事件監(jiān)聽結(jié)束后,應(yīng)及時解綁監(jiān)聽器
const locationChangeListener = function (res) {
console.log('location change', res)
}
wx.onLocationChange(locationChangeListener)
wx.startLocationUpdate()
// 監(jiān)聽結(jié)束后
wx.stopLocationUpdate()
// 修復(fù)方法:不使用后及時解綁監(jiān)聽
// wx.offLocationChange(locationChangeListener)
# 5.3 未清理的定時器
開發(fā)者在開發(fā)如「秒殺倒計時」等功能時,可能會使用 setInterval 設(shè)置定時器,頁面或組件銷毀前,需要調(diào)用 clearInterval 方法取消定時器。