App性能優(yōu)化

廣播

** LocalBroadcastManager**

應(yīng)用程序內(nèi)部廣播通信,優(yōu)先采用LocalBroadcastManager窖张,安全性更好隅熙,運行效率更高。

優(yōu)勢:平時常說BroadcastReceiver森逮,采用的是Binder通信方式,這是跨進程的通信方式磁携,系統(tǒng)資源消耗固然更多褒侧。而廣播LocalBroadcastManager,采用的是Handler通信機制谊迄,Handler的實現(xiàn)是應(yīng)用內(nèi)的通信方式闷供,所以效率與安全性都更高。

用法:

  1. 創(chuàng)建廣播接收者
//廣播類型
public static final String ACTION_SEND = "1";
//自定義廣播接收者
public class AppBroadcastReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
      //TODO
  }
}
//創(chuàng)建廣播接收者
AppBroadcastReceiver appReceiver = new AppBroadcastReceiver();
  1. 注冊廣播
LocalBroadcastManager.getInstance(context).registerReceiver(appReceiver, new IntentFilter(ACTION_SEND));

注:LocalBroadcastManager注冊廣播只能通過代碼注冊的方式统诺,而不能通過xml中靜態(tài)配置歪脏,本地廣播并沒有走系統(tǒng)廣播的流程。

  1. 發(fā)送廣播
LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(ACTION_SEND));
  1. 取消廣播
LocalBroadcastManager.getInstance(context).unregisterReceiver(appReceiver);

線程池

線程創(chuàng)建優(yōu)先采用線程池ThreadPoolExecutor粮呢,而不是new Thread()婿失; 另外設(shè)置線程優(yōu)先級為后臺運行優(yōu)先級钞艇,能有效減少Runnable創(chuàng)建的線程和和UI線程之間的資源競爭。

優(yōu)勢:通過new Thread()來創(chuàng)建線程是比較常用的方式豪硅,而使用線程池的方式有不少優(yōu)勢如下

  • 線程可重復(fù)利用哩照,節(jié)省線程的創(chuàng)建與銷毀開銷,性能有所提升懒浮;
  • 方便控制并發(fā)線程數(shù)飘弧,提高資源的利用率,減少過多的資源競爭砚著;

用法:

//創(chuàng)建Runable對象
Runnable runnable = new Runnable() {
      @Override
      public void run() {
          android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
          //TODO
      }
  };
//創(chuàng)建線程池
ExecutorService threadPoolExecutor = new ThreadPoolExecutor(
  corePoolSize, maximumPoolSize,
  keepAliveTime, unit, workQueue);
//執(zhí)行runnable
threadPoolExecutor.execute(runnable);

對于corePoolSize次伶,一般往往可以設(shè)置為Runtime.getRuntime().availableProcessors(),代表當(dāng)前系統(tǒng)活躍的CPU個數(shù)稽穆。

另外系統(tǒng)采用工廠模式冠王,通過設(shè)置ThreadPoolExecutor的不同參數(shù),提供四種默認線程池:

  1. ThreadPoolExecutor
    可緩存線程池秧骑,若線程空閑60s則回收版确,若無空閑線程可無限創(chuàng)建新線程,定義如下:
    new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
    調(diào)用方法:
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
cachedThreadPool.execute(runnable);
  1. ** newFixedThreadPool**定長線程乎折,固定線程池大小,定義如下:
    new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
    調(diào)用方法:
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(nThreads);
fixedThreadPool.execute(runnable);
  1. ** newSingleThreadExecutor**只有一個線程的線程池侵歇,定義如下:
    new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()));
    調(diào)用方法:
ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
newSingleThreadExecutor.execute(runnable);
  1. ** newScheduledThreadPool**可定時周期執(zhí)行的線程池骂澄,定義如下:
    new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue());
    調(diào)用方法:
ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(corePoolSize);
scheduledThreadPool.schedule(runnable, delay, TimeUnit.SECONDS);

ArrayList Vs LinkedList

ArrayList基于動態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu), 對于隨機訪問(get/set)惕虑,ArrayList效率比LinkedList高坟冲; LinkedList基于鏈表的數(shù)據(jù)結(jié)構(gòu),對于新增和刪除(add/remove)溃蔫,LinedList效率比ArrayList高健提;

  1. 對于list, 優(yōu)先選擇ArrayList,除非少數(shù)需要大量的插入/刪除操作才使用LinkedList伟叛。因為當(dāng)數(shù)據(jù)量非常大時get操作私痹,LinkedList時間復(fù)雜度為o(n), 而ArrayList時間復(fù)雜度為o(1)。

  2. 循環(huán)遍歷
    LinkedList采用foreach方式统刮, 效率最高紊遵。for循環(huán)方式效率大幅度降低。

List<Integer> list = new LinkedList<Integer>();
for (Integer j : list) {
  ... //TODO
}

ArrayList采用for循環(huán)+臨時變量保存size侥蒙,效率最高暗膜。 foreach方式效率略微降低。

List<Integer> list = new ArrayList<Integer>();
int len = list.size();
for (int j = 0; j < len; j++) {
  list.get(j);
}
  1. 采用new ArrayList()方式鞭衩,初始大小為0学搜,首次增加數(shù)組時娃善,擴充大小到12,以后到數(shù)組需要增長時瑞佩,會將大小增加50%会放,并將原來的成員全部復(fù)制到新的數(shù)組內(nèi)。所以盡可能將ArrayList提前設(shè)置成目標(biāo)大小钉凌,或者接近目標(biāo)大小咧最,以減少數(shù)組不斷創(chuàng)建與復(fù)制的過程,提高效率御雕。

HashMap Vs SparseArray

  1. 同時需要key和value矢沿,采用如下遍歷方法:
Map<String, String> map = new HashMap<String, String>();
for (Map.Entry<String, String> entry : map.entrySet()) {
      entry.getKey();
      entry.getValue();
}
  1. 只需要獲取key,采用如下遍歷方法:
Map<String, String> map = new HashMap<String, String>();
for (String key : map.keySet()) {
  // key process
}
  1. 當(dāng)HashMap的key是整型時酸纲,采用SparseArray捣鲸,效率更高。避免了對key與value的自動裝箱與解箱操作

Bitmap

  1. 使用BitmapFactory.Options對圖片進行縮略讀让銎隆栽惶;減小內(nèi)存使用量;
  • inSampleSize:縮放比例疾嗅,在把圖片載入內(nèi)存之前外厂,先計算出一個合適的縮放比例,避免不必要的大圖載入
  • decode format:解碼格式代承,選擇ARGB_8888/RBG_565/ARGB_4444/ALPHA_8汁蝶,能減小內(nèi)存空間
  1. 使用SoftReference:當(dāng)內(nèi)存不足時,虛擬機會自動回收它论悴;
  2. 使用Bitmap.recycle()釋放圖片掖棉,虛擬機gc時回收Bitmap;
  3. 根據(jù)手機尺寸大小,配置不同大小的圖片膀估,保證使用盡可能小的圖片資源幔亥。

Object Pool

內(nèi)存對象,通過對象池技術(shù)來達到重復(fù)利用察纯,減少對象重復(fù)創(chuàng)建帕棉。,從而減少內(nèi)存分配和回收捐寥。

  1. 復(fù)用系統(tǒng)自帶的資源笤昨,framework-res.apk中包含很多內(nèi)置資源,比如字符串/顏色/圖片/樣式/布局等握恳÷髦希可減少APK大小、內(nèi)存開銷乡洼。
  2. 緩存算法LRU

Job Scheduler

使用Job Scheduler崇裁,應(yīng)用需要做的事情就是判斷哪些任務(wù)是不緊急的匕坯,可以交給Job Scheduler來處理,Job Scheduler集中處理收到的任務(wù)拔稳,選擇合適的時間葛峻,合適的網(wǎng)絡(luò),再一起進行執(zhí)行巴比。

Android 避免使用Enum

Enum比靜態(tài)常量术奖,至少需要多過于2倍以上的內(nèi)存空間,應(yīng)該在Android中避免使用枚舉轻绞。

onDraw()

由于onDraw方法調(diào)用比較頻繁采记,需避免對象創(chuàng)建操作,因為迅速增加內(nèi)存政勃,同樣引起頻繁的gc唧龄,甚至內(nèi)存抖動。

其他

  • 內(nèi)部類引用導(dǎo)致Activity的泄漏奸远,尤其是Handler
  • 監(jiān)聽器即使注銷
  • 考慮使用Application Context而不是Activity Context
  • onLowMemory()與onTrimMemory()
  • 使用nano protobufs序列化數(shù)據(jù)
  • 使用IntentService
  • Adapter 利用convertView.getTag()與 ViewHolder
  • 窗口默認有一個不透明的背景既棺,可以去掉的: getWindow().setBackground(null),或者修改xml
  • UI局部刷新
  • 在性能敏感的代碼,避免創(chuàng)建Java對象懒叛。比如onMeasure(), onLayout(), onDraw()丸冕, getView()等
  • 使用弱引用

相關(guān)資料

http://developer.android.com/training/displaying-bitmaps/index.html
http://www.trinea.cn/android/hashmap-loop-performance/
http://hukai.me/android-performance-oom/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市芍瑞,隨后出現(xiàn)的幾起案子晨仑,更是在濱河造成了極大的恐慌,老刑警劉巖拆檬,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異妥凳,居然都是意外死亡竟贯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門逝钥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來屑那,“玉大人,你說我怎么就攤上這事艘款〕旨剩” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵哗咆,是天一觀的道長蜘欲。 經(jīng)常有香客問我,道長晌柬,這世上最難降的妖魔是什么姥份? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任郭脂,我火速辦了婚禮,結(jié)果婚禮上澈歉,老公的妹妹穿的比我還像新娘展鸡。我一直安慰自己,他們只是感情好埃难,可當(dāng)我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布莹弊。 她就那樣靜靜地躺著,像睡著了一般涡尘。 火紅的嫁衣襯著肌膚如雪忍弛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天悟衩,我揣著相機與錄音剧罩,去河邊找鬼。 笑死座泳,一個胖子當(dāng)著我的面吹牛惠昔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播挑势,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼镇防,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了潮饱?” 一聲冷哼從身側(cè)響起来氧,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎香拉,沒想到半個月后啦扬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡凫碌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年扑毡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盛险。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡瞄摊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出苦掘,到底是詐尸還是另有隱情换帜,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布鹤啡,位于F島的核電站惯驼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏揉忘。R本人自食惡果不足惜跳座,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一端铛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧疲眷,春花似錦禾蚕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至几颜,卻和暖如春倍试,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蛋哭。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工县习, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人谆趾。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓躁愿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親沪蓬。 傳聞我的和親對象是個殘疾皇子彤钟,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法跷叉,內(nèi)部類的語法逸雹,繼承相關(guān)的語法,異常的語法云挟,線程的語...
    子非魚_t_閱讀 31,631評論 18 399
  • 當(dāng)出現(xiàn)App啟動慢梆砸、界面跳轉(zhuǎn)慢、事件相應(yīng)慢园欣、滑動和動畫卡頓辫樱、展現(xiàn)內(nèi)容慢等問題的時候意味著App性能出現(xiàn)問題,這個時...
    Kurtis閱讀 310評論 0 0
  • 一般我們寫的app操作的數(shù)據(jù)多的時侯或者平時使用的時候都會經(jīng)常出現(xiàn)卡頓俊庇、閃退、ANR停止運行等各種問題鸡挠。這樣會導(dǎo)致...
    踏雪羽翼閱讀 589評論 0 1
  • 父母給予你善良的樣貌 你跟隨命運辉饱,成為一個善良的人 即使你是披著羊皮的狼 在眾人眼里你仍是善良之輩 父母給予你老實...
    鹿原先生和蓬蒿閱讀 303評論 6 9
  • Art藝生活閱讀 791評論 0 0