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

歡迎訪問 生活随笔!

生活随笔

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

Android

Android性能调优实例

發(fā)布時(shí)間:2023/12/14 Android 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android性能调优实例 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
本文主要分享自己在appstore項(xiàng)目中的性能調(diào)優(yōu)點(diǎn),包括 同步改異步、緩存、Layout優(yōu)化、數(shù)據(jù)庫優(yōu)化、算法優(yōu)化、延遲執(zhí)行等。
一、性能瓶頸點(diǎn)
整個(gè)頁面主要由6個(gè)Page的ViewPager,每個(gè)Page為一個(gè)GridView,GridView一屏大概顯示4*4的item信息(本文最后有附圖)。由于網(wǎng)絡(luò)數(shù)據(jù)獲取較多且隨時(shí)需要保持頁面內(nèi)app下載進(jìn)度及狀態(tài),所以出現(xiàn)以下性能問題
a.??ViewPager左右滑動(dòng)明顯卡頓
b.??GridView上下滾動(dòng)明顯卡頓
c.??其他Activity返回ViewPager Activity較慢
d.??網(wǎng)絡(luò)獲取到展現(xiàn)速度較慢

二、性能調(diào)試及定位
主要使用 Traceview、monkey、monkey runner調(diào)試,traceview類似java web調(diào)優(yōu)的visualvm,使用方法如下:
在需要調(diào)優(yōu)的activity onCreate函數(shù)中添加
  • <font style="background-color:rgb(254, 253, 231)"><font face="Georgia,">android.os.debug.startMethodTracing("Entertainment");</font></font>
  • 復(fù)制代碼 onDestrory函數(shù)中添加
  • <font style="background-color:rgb(254, 253, 231)"><font face="Georgia,">android.os.debug.stopMethodTracing();</font></font>
  • 復(fù)制代碼 程序退出后會(huì)在sd卡根目錄下生成Entertainment.trace這個(gè)文件,cmd到android sdk的tools目錄下運(yùn)行traceview.bat Entertainment.trace即可,截圖如下
    從中可以看出各個(gè)函數(shù)的調(diào)用時(shí)間、調(diào)用次數(shù)、平均調(diào)用時(shí)間、時(shí)間占用百分比等從而定位到耗時(shí)的操作。monkey、monkey runner更詳細(xì)的見后面博客介紹
    三、性能調(diào)優(yōu)點(diǎn)
    主要包括同步改異步、緩存、Layout優(yōu)化、數(shù)據(jù)庫優(yōu)化、算法優(yōu)化、延遲執(zhí)行。
    1. 同步改異步
    這個(gè)就不用多講了,耗時(shí)操作放在線程中執(zhí)行防止占用主線程,一定程度上解決anr。
    但需要注意線程和service結(jié)合(防止activity被回收后線程也被回收)以及線程的數(shù)量(后面優(yōu)化介紹)
    PS:請(qǐng)使用java的線程池(后面介紹),少使用AsyncTask,因?yàn)锳syncTask存在性能問題(以后會(huì)單獨(dú)博文介紹)
    2. 緩存
    java的對(duì)象創(chuàng)建需要分配資源較耗費(fèi)時(shí)間,加上創(chuàng)建的對(duì)象越多會(huì)造成越頻繁的gc影響系統(tǒng)響應(yīng)。主要使用單例模式、緩存(圖片緩存、線程池、View緩存、IO緩存、消息緩存、通知欄notification緩存)及其他方式減少對(duì)象創(chuàng)建。
    (1). 單例模式
    對(duì)于創(chuàng)建開銷較大的類可使用此方法,保證全局一個(gè)實(shí)例,在程序運(yùn)行過程中該類不會(huì)因新建額外對(duì)象產(chǎn)生開銷。示例代碼如下:
  • class Singleton {
  • ? ? private static Singleton instance = null;

  • ? ? private Singleton() {
  • ? ?? ???}

  • ? ? public static synchronized Singleton getInstance() {
  • ? ?? ???if (instance == null) {
  • ? ?? ?? ?? ?instance = new Singleton();
  • ? ?? ???}
  • ? ?? ???return instance;
  • ? ? }
  • }
  • 復(fù)制代碼 (2). 緩存
    程序中用到了圖片緩存、線程池、View緩存、IO緩存、消息緩存、通知欄notification緩存等。
    a. 圖片緩存:見ImageCache和ImageSdCache
    b. 線程池:使用Java的Executors類,通過newCachedThreadPool、newFixedThreadPool、newSingleThreadExecutor、newScheduledThreadPool提供四種不同類型的線程池
    c. View緩存:
  • @Override
  • public View getView(int position, View convertView, ViewGroup parent) {
  • ? ?? ???ViewHolder holder;
  • ? ?? ???if (convertView == null) {
  • ? ?? ?? ?? ?? ? convertView = inflater.inflate(R.layout.type_item, null);
  • ? ?? ?? ?? ?? ? holder = new ViewHolder();
  • ? ?? ?? ?? ?? ? holder.imageView = (ImageView)convertView.findViewById(R.id.app_icon);
  • ? ?? ?? ?? ?? ? holder.textView = (TextView)convertView.findViewById(R.id.app_name);
  • ? ?? ?? ?? ?? ? convertView.setTag(holder);
  • ? ?? ???} else {
  • ? ?? ?? ?? ?? ? holder = (ViewHolder)convertView.getTag();
  • ? ?? ???}
  • ? ?? ???holder.imageView.setImageResource(R.drawable.index_default_image);
  • ? ?? ???holder.textView.setText("");
  • ? ?? ???return convertView;
  • }

  • /**
  • * ViewHolder
  • */
  • static class ViewHolder {

  • ? ?? ???ImageView imageView;
  • ? ?? ???TextView??textView;
  • }
  • 復(fù)制代碼 通過convertView是否為null減少layout inflate次數(shù),通過靜態(tài)的ViewHolder減少findViewById的次數(shù),這兩個(gè)函數(shù)尤其是inflate是相當(dāng)費(fèi)時(shí)間的
    d. IO緩存:
    使用具有緩存策略的輸入流,BufferedInputStream替代InputStream,BufferedReader替代Reader,BufferedReader替代BufferedInputStream.對(duì)文件、網(wǎng)絡(luò)IO皆適用。
    e. 消息緩存:通過Handler的obtainMessage回收就的Message對(duì)象,減少M(fèi)essage對(duì)象的創(chuàng)建開銷
    handler.sendMessage(handler.obtainMessage(1));
    f. 通知欄notification緩存:下載中需要不斷改變通知欄進(jìn)度條狀態(tài),如果不斷新建Notification會(huì)導(dǎo)致通知欄很卡。這里我們可以使用最簡(jiǎn)單的緩存
    Map<String, Notification> notificationMap = new HashMap<String, Notification>();如果notificationMap中不存在,則新建notification并且put into map.
    (3). 其他
    能創(chuàng)建基類解決問題就不用具體子類:除需要設(shè)置優(yōu)先級(jí)的線程使用new Thread創(chuàng)建外,其余線程創(chuàng)建使用new Runnable。因?yàn)樽宇悤?huì)有自己的屬性創(chuàng)建需要更多開銷。
    控制最大并發(fā)數(shù)量:使用Java的Executors類,通過Executors.newFixedThreadPool(nThreads)控制線程池最大線程并發(fā)
    對(duì)于http請(qǐng)求增加timeout 3. Layout優(yōu)化
    性能優(yōu)化相關(guān)的一些標(biāo)簽 <viewStub/>,<merge/>和<include/> 可見: http://hexen.blog.51cto.com/1110171/820197
    TextView屬性優(yōu)化:TextView的android:ellipsize=”marquee”跑馬燈效果極耗性能,具體原因還在深入源碼中
    對(duì)于layout中的布局實(shí)際效果可使用hierarchyviewer查看
    對(duì)于layout中多余的view以及不正確的標(biāo)簽可使用android lint查看

    4. 數(shù)據(jù)庫優(yōu)化
    主要包括sql優(yōu)化、建立索引、使用事務(wù)、讀寫表區(qū)分
    (1). sql優(yōu)化
    可參考http://database.51cto.com/art/200904/118526.htm

    (2). 建立索引
    使用CREATE INDEX mycolumn_index ON mytable (myclumn)語句在SQLiteOpenHelper子類的onCreate或onUpgrade函數(shù)創(chuàng)建索引,索引創(chuàng)建后對(duì)大數(shù)據(jù)量的查詢性能提升效果較明顯(3). 使用事務(wù)
    事務(wù)不僅能保證批量操作一起完成或回滾,而且在大量插入、更新、查詢時(shí)減少程序和表的交互從而提高性能
  • SQLiteDatabase db = dbHelper.getWritableDatabase();
  • db.beginTransaction();
  • try {
  • ? ?? ???// add to do
  • ? ?? ???db.setTransactionSuccessful();
  • } catch (Exception e) {
  • ? ?? ???Log.e(TAG, e.toString());
  • } finally {
  • ? ?? ???db.endTransaction();
  • }
  • 復(fù)制代碼 (4). 讀寫表區(qū)分對(duì)于查詢操作使用dbHelper.getReadableDatabase();讀表代替寫表。因?yàn)閟qlite是表級(jí)鎖,所以修改和插入等寫操作的性能較差。
    5. 算法優(yōu)化
    這個(gè)就是個(gè)博大精深的話題了,只介紹本應(yīng)用中使用的。
    使用hashMap代替arrayList,時(shí)間復(fù)雜度降低一個(gè)數(shù)量級(jí)
    6. 延遲執(zhí)行
    對(duì)于很多耗時(shí)邏輯沒必要立即執(zhí)行,這時(shí)候我們可以將其延遲執(zhí)行。
    線程延遲執(zhí)行 ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10);
    消息延遲發(fā)送 handler.sendMessageDelayed(handler.obtainMessage(0), 1000);
    四、本程序性能調(diào)優(yōu)結(jié)果
    1. ViewPager左右滑動(dòng)明顯卡頓
    2. GridView上下滾動(dòng)明顯卡頓
    (1). 去掉TextView的android:ellipsize=”marquee”
    (2). 修改圖片緩存的最大線程數(shù),增加http timeout
    (3). 修改設(shè)置app是否已安裝的狀態(tài),具體代碼修改如下:
  • List<PackageInfo> installedPackageList = getPackageManager().getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
  • List<App> installedAppList = function(installedAppList)
  • for (App app : appList) {
  • ? ?? ???for (App installedApp : installedAppList) {

  • ? ?? ???}
  • }
  • 復(fù)制代碼 修改為
  • for (App app : appList) {
  • ? ?? ???Pair<Integer, String> versionInfo = INSTALLED_APP_MAP.get(app.getPackageName());
  • ? ?? ???if (versionInfo != null) {

  • ? ?? ???} else {

  • ? ?? ???}
  • }
  • 復(fù)制代碼 從每次獲取List<PackageInfo> installedAppList = getPackageManager().getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);修改為只在有應(yīng)用安裝或卸載廣播時(shí)獲取應(yīng)用列表,并且用hashMap代替installedAppList減少查詢時(shí)間。將平均執(zhí)行時(shí)間從201ms降低到1ms。
    3. 其他Activity返回ViewPager Activity較慢
    定位:在onStart函數(shù)
    解決:使用延遲策略,具體代碼修改如下:
  • @Override
  • public void onStart() {
  • ? ?? ???super.onStart();
  • ? ?? ???appUpdateListAdapter.notifyDataSetChanged();
  • }
  • 復(fù)制代碼 4. 網(wǎng)絡(luò)獲取到展現(xiàn)速度較慢定位:在HttpURLConnection.getInputStream()之后的處理
    解決:使用BufferedReader替代BufferedInputStream獲取時(shí)間從100ms降低到3ms,具體代碼修改如下:
  • HttpURLConnection con = (HttpURLConnection)url.openConnection();
  • InputStream input = con.getInputStream();
  • while (input.read(buffer, 0, 1024) != -1) {

  • }
  • 復(fù)制代碼 改為
  • HttpURLConnection con = (HttpURLConnection)url.openConnection();
  • BufferedReader input = new BufferedReader(new InputStreamReader(con.getInputStream()));
  • String s;
  • while ((s = input.readLine()) != null) {

  • }
  • 復(fù)制代碼

    總結(jié)

    以上是生活随笔為你收集整理的Android性能调优实例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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