日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android异常与性能优化相关问题及解决办法

發(fā)布時間:2024/1/8 Android 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android异常与性能优化相关问题及解决办法 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

  • ANR異常問題及解決方式
  • OOM異常問題及解決方式
  • BitMap相關(guān)問題
  • UI卡頓問題
  • 內(nèi)存泄露問題及解決方式
  • 內(nèi)存管理
  • 冷啟動優(yōu)化問題
  • 其他優(yōu)化介紹

ANR異常問題及解決方式

什么是ANR


ANR全名Application Not Responding, 也就是”應(yīng)用無響應(yīng)”. 當(dāng)操作在一段時間內(nèi)系統(tǒng)無法處理時, 系統(tǒng)層面會彈出上圖那樣的ANR對話框.

造成ANR的主要原因

在Android里, App的響應(yīng)能力是由Activity Manager和Window Manager系統(tǒng)服務(wù)來監(jiān)控的. 通常在如下兩種情況下會彈出ANR對話框:

  • 5s內(nèi)無法響應(yīng)用戶輸入事件(例如鍵盤輸入, 觸摸屏幕等).
  • BroadcastReceiver在10s內(nèi)無法結(jié)束.

造成以上兩種情況的首要原因就是在主線程(UI線程)里面做了太多的阻塞耗時操作, 例如文件讀寫, 數(shù)據(jù)庫讀寫, 網(wǎng)絡(luò)查詢等等.

那么Android中哪些操作是在主線程尼?

  • Activity的所有生命周期都是執(zhí)行在主線程
  • Service默認是執(zhí)行在主線程
  • BroadcastReceiver的onReceiver回調(diào)是執(zhí)行在主線程的
  • 沒有使用子線程的looper的Handler的handleMessage,post(Runnnable)是執(zhí)行在主線程的。
  • AsyncTask的回調(diào)中除了donInbackground,其他都在主線程中執(zhí)行。

如何解決ANR

  • 使用AsyncTask處理耗時操作
  • 使用Thread或者HandlerThread提高優(yōu)先級
  • 使用handler來處理工作線程的耗時操作
  • Activity的onCreate和onResume回調(diào)中盡量避免耗時的代碼

OOM異常問題及解決方式

什么是OOM?

當(dāng)前占用的內(nèi)存加上我們申請的內(nèi)存資源超過了Dalvik虛擬機的最大內(nèi)存限制就會拋出的Out of memory 異常。

一些容易混淆的概念

內(nèi)存溢出:即是OOM
內(nèi)存抖動:因為短時間內(nèi)創(chuàng)建大量的對象,然后瞬間釋放,這段時間占有的內(nèi)存區(qū)域,會產(chǎn)生抖動。
內(nèi)存泄露:產(chǎn)生內(nèi)存垃圾,無法被GC回收。

如何解決OOM

產(chǎn)生OOM有以下方式:

  • 1.數(shù)據(jù)庫的cursor沒有關(guān)閉。
  • 2.構(gòu)造adapter沒有使用緩存contentview。
  • 3.調(diào)用registerReceiver()后未調(diào)用unregisterReceiver().
  • 4.未關(guān)閉InputStream/OutputStream。
  • 5.Bitmap使用后未調(diào)用recycle(),控制圖像縮放大小,使用inBitmap屬性,三級緩存
  • 6.Context泄漏。
  • 7.static關(guān)鍵字等。
  • 8.避免在onDraw方法里執(zhí)行對象的創(chuàng)建
  • 9.謹慎使用多進程

BitMap相關(guān)問題

  • 1.recycle
  • 2.LRU
  • 3.計算inSampleSize,使用縮略圖
  • 4.三級緩存
  • 5.軟引用

雖然,系統(tǒng)能夠確認Bitmap分配的內(nèi)存最終會被銷毀,但是由于它占用的內(nèi)存過多,所以很可能會超過java堆的限制。因此,在用完Bitmap時,要 及時的recycle掉。recycle并不能確定立即就會將Bitmap釋放掉,但是會給虛擬機一個暗示:“該圖片可以釋放了”, 還有就是, 雖然recycle()從源碼上看,調(diào)用它應(yīng)該能立即釋放Bitmap的主要內(nèi)存,但是測試表明它并沒能立即釋放內(nèi)存。故我們還需手動設(shè)置為NULL這樣 還能大大的加速Bitmap的主要內(nèi)存的釋放。。
如下:

if(!bitmap.isRecycled()){bitmap.recycle()}

對于LRU 請移步我的另一篇博客 Android中LruCache案例及實現(xiàn)原理分析

有時候,我們要顯示的區(qū)域很小,沒有必要將整個圖片都加載出來,而只需要記載一個縮小過的圖片,這時候可以設(shè)置一定的采樣率,那么就可以大大減小占用的內(nèi)存。如下面的代碼:

/*** Return the sample size.** @param options The options.* @param maxWidth The maximum width.* @param maxHeight The maximum height.* @return the sample size*/private static int calculateInSampleSize(final BitmapFactory.Options options,final int maxWidth,final int maxHeight) {int height = options.outHeight;int width = options.outWidth;int inSampleSize = 1;while ((width >>= 1) >= maxWidth && (height >>= 1) >= maxHeight) {inSampleSize <<= 1;}return inSampleSize;}private static boolean isEmptyBitmap(final Bitmap src) {return src == null || src.getWidth() == 0 || src.getHeight() == 0;}/*** Return the compressed bitmap using sample size.** @param src The source of bitmap.* @param maxWidth The maximum width.* @param maxHeight The maximum height.* @param recycle True to recycle the source of bitmap, false otherwise.* @return the compressed bitmap*/public static Bitmap compressBySampleSize(final Bitmap src,final int maxWidth,final int maxHeight,final boolean recycle) {if (isEmptyBitmap(src)) return null;BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;ByteArrayOutputStream baos = new ByteArrayOutputStream();src.compress(Bitmap.CompressFormat.JPEG, 100, baos);byte[] bytes = baos.toByteArray();BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);options.inSampleSize = calculateInSampleSize(options, maxWidth, maxHeight);options.inJustDecodeBounds = false;if (recycle && !src.isRecycled()) src.recycle();return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options); }

附上關(guān)于BitMap工具類下載地址

巧妙的運用軟引用(SoftRefrence)
有些時候,我們使用Bitmap后沒有保留對它的引用,因此就無法調(diào)用Recycle函數(shù)。這時候巧妙的運用軟引用,可以使Bitmap在內(nèi)存快不足時得到有效的釋放。如下例:

private class MyAdapter extends BaseAdapter { private ArrayList> mBitmapRefs = new ArrayList>(); public View getView(int i, View view, ViewGroup viewGroup) { View newView = null; if(view != null) { newView = view; } else { newView =(View)mInflater.inflate(R.layout.image_view, false); } Bitmap bitmap = BitmapFactory.decodeFile(mValues.get(i).fileName); mBitmapRefs.add(new SoftReference(bitmap)); //此處加入ArrayList ((ImageView)newView).setImageBitmap(bitmap); return newView; } }

通過使用三級緩存請移步我的另一篇博客 Android中三級緩存實現(xiàn)原理及案例分析

UI卡頓問題

UI卡頓原理

不卡頓情況要60幀操作需要在16ms時間完成,如果完成不了,那么就會造成卡頓現(xiàn)象,渲染失敗,還有一種情況是overDraw情況,一般是重疊View,非必要重疊背景

UI卡頓原因分析

1、人為在UI線程中做輕微耗時操作,導(dǎo)致UI線程卡頓
2、布局Layout過于復(fù)雜,無法在16ms內(nèi)存完成渲染
3、同一時間動畫執(zhí)行的次數(shù)過多,導(dǎo)致CPU或GPU負載過重
4、View過度繪制,導(dǎo)致某些像素在同一幀時間內(nèi)被繪制多次,從而使CPU或GPU負載過重
5、View頻繁的觸發(fā)measure、layout,導(dǎo)致measure、layout累計耗時過多及整個View頻繁的重新渲染
6、內(nèi)存頻繁觸發(fā)GC過多,導(dǎo)致暫時阻塞渲染操作
7、冗余資源及邏輯等導(dǎo)致加載和執(zhí)行緩慢
8、ANR

UI卡頓總結(jié)

1、布局優(yōu)化:不使用太多嵌套,使用weight 代替長和寬的計算,使用Gone代替invisible
2、列表及Adapter優(yōu)化
3、背景和圖片等內(nèi)存分配優(yōu)化
4、避免ANR

內(nèi)存泄露問題及解決方式

java內(nèi)存泄露基礎(chǔ)知識

1、java內(nèi)存的分配策略

寄存器:我們在程序中無法控制
棧:存放基本類型的數(shù)據(jù)和對象的引用,但對象本身不存放在棧中,而是存放在堆中
堆:存放用new產(chǎn)生的數(shù)據(jù)
靜態(tài)域:存放在對象中用static定義的靜態(tài)成員
常量池:存放常量
非RAM(隨機存取存儲器)存儲:硬盤等永久存儲空間

2、java是如何管理內(nèi)存的

java管理內(nèi)存實際上就是對象的生成與釋放的管理,對象的生成是在堆中生成的,釋放是靠GC回收機制,前者是程序員控制,后者靠java虛擬機控制,下面是一個案例:

3、java中的內(nèi)存泄露

內(nèi)存泄露是指無用對象(不再使用的對象)持續(xù)占有內(nèi)存或無用對象的內(nèi)存得不到及時釋放,從而造成的內(nèi)存空間的浪費稱為內(nèi)存泄露

  • 單例引起的內(nèi)存泄漏

使與應(yīng)用生命周期一樣長,持有該對象的引用,

內(nèi)存泄露問題:

public class AppManager{private static AppManager instance;private Context mcontext;private AppManager(){}private AppManager(Context context){mcontext=context;}private static AppManager getInstance(Context context){if(instance==null){instance=new AppManager(context);}return instance;}} public class AppManager{private static AppManager instance;private Context mcontext;private AppManager(){}private AppManager(Context context){mcontext=context.getApplicationContext();//使用Application的context}private static AppManager getInstance(Context context){if(instance==null){instance=new AppManager(context);}return instance;} }
  • 匿名內(nèi)部類

非靜態(tài)內(nèi)部類持有外部類的引用,而使用非靜態(tài)內(nèi)部類創(chuàng)建一個靜態(tài)實例。正確解決辦法是將該類變?yōu)殪o態(tài)類

  • handler

原因:非靜態(tài)內(nèi)部類持有外部類的引用。

handler造成的內(nèi)存泄漏解決辦法:

private MyHandler mHandler = new MyHandler(this); private TextView mTextView; private static class MyHandler extends Handler{private WeekReference<Context> reference;public MyHandler(Context context){reference=new WeekReference<>(context);}@Overridepublic void handleMessage(Message msg){MainActivity activity=(MainActivity)reference.get();if(activity!=null){activity.mTextview.setText("");}}}
  • 避免使用static變量
  • 資源未關(guān)閉造成的內(nèi)存泄露。
  • AsyncTask造成的內(nèi)存泄露

原因:非靜態(tài)內(nèi)部類持有外部類引用;

解決辦法:

在Activity的onDestory方法中調(diào)用AsyncTask的cancel方法。

4、內(nèi)存優(yōu)化方法

  • 當(dāng)Service完成任務(wù)后,盡量停止它;
  • 在UI不可見的時候,釋放掉一些只有UI使用的資源;
  • 在系統(tǒng)內(nèi)存緊張的時候,盡可能多的釋放掉一些非重要的資源;
  • 避免濫用BitMap導(dǎo)致的內(nèi)存浪費
  • 使用針對內(nèi)存優(yōu)化過的數(shù)據(jù)容器 SpareArray代替HashMap 枚舉類型常量是一般常量類型占用內(nèi)存的兩倍
  • 避免使用依賴注入的框架
  • 使用ZIP對齊的APK
  • 使用多進程,比如通過開啟進程 解決開啟定位,開啟推送,開啟webview加載url

冷啟動優(yōu)化

冷啟動的定義及與熱啟動的區(qū)別

冷啟動:就是在啟動應(yīng)用前,系統(tǒng)中沒有該應(yīng)用的任何進程信息。會初始化Application類
熱啟動:用戶使用返回鍵退出應(yīng)用,然后馬上又重新啟動應(yīng)用。不會初始化Application類

冷啟動的時間計算:

這個時間從應(yīng)用啟動(創(chuàng)建進程)開始計算,到完成視圖的第一次繪制(即Activity內(nèi)容對用戶可見)為止。

冷啟動流程:

1、Zygote進程中fork創(chuàng)建出一個新的進程,
2、創(chuàng)建和初始化Application類、創(chuàng)建MainActivity類,inflate布局;
3、當(dāng)onCreate/onStart/onResume方法走完,contentView的measure/layout/draw顯示在桌面上

冷啟動流程-總結(jié):

Application的構(gòu)造方法–>attachBaseContext()—>onCreate()–>Activity的構(gòu)造方法–>onCreate()–>配置主題中背景等屬性–>onStart()–>onResume()–>測量布局繪制顯示在桌面上。

如何對冷啟動的時間進行優(yōu)化

1、減少onCreate()方法的工作量
2、不讓Application參與業(yè)務(wù)的操作
3、不要在Application進行耗時操作
4、不要以靜態(tài)變量的方式在Application中保存數(shù)據(jù)
5、布局/mainThread

其他優(yōu)化:

  • android不要靜態(tài)變量存儲數(shù)據(jù)

1、靜態(tài)變量等數(shù)據(jù)由于進程已經(jīng)被殺死而被初始化
2、使用其他數(shù)據(jù)傳輸方式:文件/sp/contentProvider

  • 有關(guān)Sharepreference問題

1、不能跨進程同步數(shù)據(jù)讀寫操作
2、存儲Sharepreference的文件過大問題,可能引起ui卡頓,

  • 內(nèi)存對象序列化

1、實現(xiàn)Serializeble接口
2、Parcelable (不適用磁盤數(shù)據(jù)序列化)

總結(jié):Serializeble是java的序列化方式,Parcelable是Android特有的序列化方式,在使用內(nèi)存的時候,Parcelable比Serializable性能高
Serializable在序列化的時候會產(chǎn)生大量的臨時變量,從而引起頻繁的GC操作,Parcelable不能使用在要將數(shù)據(jù)存貯在磁盤的情況

總結(jié)

以上是生活随笔為你收集整理的Android异常与性能优化相关问题及解决办法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。