性能優(yōu)化處理
圖片的性能優(yōu)化
- 一個(gè)activity 空置時(shí) 只需要3M的空間(當(dāng)然這里是包括Application所占用的空間的)
例子:本地添加一個(gè)比較大的圖,900K ,在登錄顯示的時(shí)候 直接加載這張圖(加載的方式 是直接獲取本地的drawable 和 bitmap),看內(nèi)存消耗,80M。
直接加載drawable 消耗內(nèi)存21M
-
直接加載bitmap(編碼格式是ARGB8888 一個(gè)像素點(diǎn)占4個(gè)字節(jié)) 消耗內(nèi)存21m(大圖顯示不全 有白邊)
針對(duì)圖片的做處理
-
針對(duì)Bitmap做編碼格式的處理(ARGB565 一個(gè)像素點(diǎn)占2個(gè)字節(jié)) 消耗內(nèi)存5M (效果和 ARGB8888差不多,且沒有白邊)針對(duì)當(dāng)前情況 把圖片放置在不同的drawable的密度下,看看加載的情況(加載時(shí)內(nèi)存消耗一致 但是和 將圖片放置在drawable中不一致 在drawable中會(huì)變大)
1)drawable-hdpi下 5.26M
1)drawable-xhdpi下 5.26M
1)drawable-xxhdpi下 5.26M
不同分辨率下的圖片加載 耗費(fèi)內(nèi)存:
1)增加分辨率之后 耗費(fèi)內(nèi)存是 8.02M針對(duì)圖片處理,建議1.在不太要求精度的情況下 ,盡量使用AGB565處理 2.圖片進(jìn)行分類,放置在drawable-hdpi drawable-xhdpi下 drawable-xxhdpi下
2 內(nèi)存使用的優(yōu)化
1)幾個(gè)Context的認(rèn)識(shí):(上下文,就是能夠獲取到系統(tǒng)資源的類)
a)結(jié)構(gòu)如下;
-Object
-Context
-MockContext
-ContextWrapper
-TintContextWrapper
-IsolatedContext
-MutableContextWrapper
-ContextThemeWrapper
-Activity -----------------------
-Service -----------------------
-Application-----------------------
-BackupAgent
上邊的幾個(gè)Context是經(jīng)常使用到的Activity Service Application
b)生命周期:
Application 是在一個(gè)在app啟動(dòng)時(shí)就創(chuàng)建的context實(shí)例,并且application會(huì)一直存在,直到用戶將其殺死。
Activity 正常情況下,一個(gè)activity的生命周期是隨著啟動(dòng)時(shí)創(chuàng)建,在不再使用,應(yīng)該退出activity棧時(shí),就會(huì)被銷毀
Service 正常情況下 service在啟動(dòng)時(shí)創(chuàng)建,在停止時(shí)終止。(service 和ntentService 的生命周期 有區(qū)別,service是可以自己stopSelf 也可以通過(guò)Intent停止服務(wù),
但是IntentService是跟綁定的宿主生命周期關(guān)聯(lián),會(huì)隨著宿主的生命周期的結(jié)束而結(jié)束自己的生命周期)
c)獲取
在Activity中,直接使用Activity.this,getBaseContext(){因?yàn)锳ctivity都是ContextWrapper的基類,所以這里的getBaseContext都是獲取基類中的mBase參數(shù)},
看老羅的博客中 得到這樣的一個(gè)結(jié)果:activity是一個(gè)context,activity的父類是ContextWrapperTheme,而ContextWrapperTheme的父類是ContextWrapper,ContextWrapper的父類是Context.
在ContextWrapper 中有一個(gè)方法也是獲取Context的,叫g(shù)etBaseContext() 返回的是類變量mBase,這個(gè)Context是在Activity創(chuàng)建是 系統(tǒng)創(chuàng)建的,與Activity是兩個(gè)不同的Context。
通過(guò)分配的內(nèi)存地址可以看出,兩個(gè)不一樣。
Activity的創(chuàng)建 不是通過(guò)new一個(gè)對(duì)象這么簡(jiǎn)單的創(chuàng)建,看代碼是
public class Instrumentation {
......
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}
......
} 是通過(guò)class.newInstance()來(lái)創(chuàng)建的。Activity是一個(gè)復(fù)雜的類,包含了很多東西。是在ActivityThread 中創(chuàng)建的,創(chuàng)建過(guò)程可以看看源碼:
public final class ActivityThread {
......
Instrumentation mInstrumentation;
......
private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
ComponentName component = r.intent.getComponent();
......
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
......
} catch (Exception e) {
......
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
......
if (activity != null) {
ContextImpl appContext = new ContextImpl();
......
appContext.setOuterContext(activity);
......
Configuration config = new Configuration(mConfiguration);
......
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstance,
r.lastNonConfigurationChildInstances, config);
......
mInstrumentation.callActivityOnCreate(activity, r.state);
......
}
......
} catch (SuperNotCalledException e) {
......
} catch (Exception e) {
......
}
return activity;
}
} 這里創(chuàng)建了很多的東西,咱們的Context 和 getBasseContext 之所以不同,在這里就有體現(xiàn)。
同時(shí)這里還創(chuàng)建了一個(gè)Application 這樣一個(gè)ApplicationContext,這樣ApplicationContext 和 之前
所說(shuō)的兩個(gè)Activity 及getBaseContext分別是不一樣的。
d)在Service中 獲取的Context 和getBaseContext 也是不同的地址,所以不是指的同一個(gè)變量。在Activity中啟動(dòng)Service之后,
分別對(duì)Activity和Service獲取Context 及 getBaseContext來(lái)比較,是個(gè)Context的地址都不一樣。
啟動(dòng)Service的源碼沒有找到,但是看Service中存在的各變量和Activity中存在的各變量是類似,沒有找到啟動(dòng)Service中 比較深層次的源碼,
所以這里不能給出確切的認(rèn)定,service和Activity啟動(dòng)一樣(只不過(guò)Activity中有Window可以承載UI,但是Service就不能)。
e)因?yàn)榇嬖贑ontext的生命周期的說(shuō)法,所以這里要說(shuō)的是創(chuàng)建某個(gè)對(duì)象時(shí) 如果這個(gè)對(duì)象是全局的,就應(yīng)該要使用全局的Context,如果對(duì)象是局部的
那么就應(yīng)該要用局部的Context.
內(nèi)存泄漏的實(shí)例是: 推送的manager 及統(tǒng)計(jì)的manager 在創(chuàng)建的時(shí)候 是在引導(dǎo)頁(yè)。而傳入的Context直接就是引導(dǎo)頁(yè)的this.導(dǎo)致
推送的manager 統(tǒng)計(jì)的manager 因?yàn)槭庆o態(tài)單例,所以就一直持有引導(dǎo)頁(yè)的context,不被釋放。導(dǎo)致內(nèi)存泄漏。
查看工具:
AS中存在這樣一個(gè)Dump java heap的工具,這個(gè)工具能抓取手機(jī)中正在運(yùn)行的 所有應(yīng)用的在內(nèi)存中15秒的分配情況。通過(guò)class package 可以很方便的找到
當(dāng)前的應(yīng)用的包下存在哪些對(duì)象,對(duì)象的個(gè)數(shù)。