Android CPU使用率:top和dump cpuinfo的不同
CPU是系統非常重要的資源,在Android中,檢視CPU使用情況,可以使用top命令和dump cpuinfo。我記得很久以前,就發現這兩者存在不同,初步猜測應該是演算法上存在差異。最近需要採集應用CPU的使用率,看了一下兩種CPU的計算方法。
1、top
top是比較經典的CPU計算方法,top的程式碼在androidm/system/core/toolbox/top.c下面,輸出process的cpu使用率在print_procs裡面:
<code class="hljs haskell has-numbering"><span class="hljs-title">static</span> void print_procs(void) { ... for (i = <span class="hljs-number">0</span>; i < num_new_procs; i++) { <span class="hljs-keyword">if</span> (new_procs[i]) { old_proc = find_old_proc(new_procs[i]->pid, new_procs[i]->tid); <span class="hljs-keyword">if</span> (old_proc) { new_procs[i]->delta_utime = new_procs[i]->utime - old_proc->utime; new_procs[i]->delta_stime = new_procs[i]->stime - old_proc->stime; } <span class="hljs-keyword">else</span> { new_procs[i]->delta_utime = <span class="hljs-number">0</span>; new_procs[i]->delta_stime = <span class="hljs-number">0</span>; } new_procs[i]->delta_time = new_procs[i]->delta_utime + new_procs[i]->delta_stime; } } total_delta_time = (new_cpu.utime + new_cpu.ntime + new_cpu.stime + new_cpu.itime + new_cpu.iowtime + new_cpu.irqtime + new_cpu.sirqtime) - (old_cpu.utime + old_cpu.ntime + old_cpu.stime + old_cpu.itime + old_cpu.iowtime + old_cpu.irqtime + old_cpu.sirqtime); ... <span class="hljs-title">if</span> (!threads) { printf(<span class="hljs-string">"%5d %2d %3"</span> <span class="hljs-type">PRIu64</span> <span class="hljs-string">"%% %c %5d %6"</span> <span class="hljs-type">PRIu64</span> <span class="hljs-string">"K %6"</span> <span class="hljs-type">PRIu64</span> <span class="hljs-string">"K %3s %-8.8s %s\n"</span>, <span class="hljs-keyword">proc</span>->pid, <span class="hljs-keyword">proc</span>->prs, <span class="hljs-keyword">proc</span>->delta_time * <span class="hljs-number">100</span> / total_delta_time, <span class="hljs-keyword">proc</span>->state, <span class="hljs-keyword">proc</span>->num_threads, <span class="hljs-keyword">proc</span>->vss / <span class="hljs-number">1024</span>, <span class="hljs-keyword">proc</span>->rss * getpagesize() / <span class="hljs-number">1024</span>, <span class="hljs-keyword">proc</span>->policy, user_str, <span class="hljs-keyword">proc</span>->name[<span class="hljs-number">0</span>] != <span class="hljs-number">0</span> ? <span class="hljs-keyword">proc</span>->name : <span class="hljs-keyword">proc</span>->tname); } <span class="hljs-keyword">else</span> { printf(<span class="hljs-string">"%5d %5d %2d %3"</span> <span class="hljs-type">PRIu64</span> <span class="hljs-string">"%% %c %6"</span> <span class="hljs-type">PRIu64</span> <span class="hljs-string">"K %6"</span> <span class="hljs-type">PRIu64</span> <span class="hljs-string">"K %3s %-8.8s %-15s %s\n"</span>, <span class="hljs-keyword">proc</span>->pid, <span class="hljs-keyword">proc</span>->tid, <span class="hljs-keyword">proc</span>->prs, <span class="hljs-keyword">proc</span>->delta_time * <span class="hljs-number">100</span> / total_delta_time, <span class="hljs-keyword">proc</span>->state, <span class="hljs-keyword">proc</span>->vss / <span class="hljs-number">1024</span>, <span class="hljs-keyword">proc</span>->rss * getpagesize() / <span class="hljs-number">1024</span>, <span class="hljs-keyword">proc</span>->policy, user_str, <span class="hljs-keyword">proc</span>->tname, <span class="hljs-keyword">proc</span>->name); } ... } </code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li></ul>
CPU的計算是proc->delta_time * 100 / total_delta_time。
先看total_delta_time由:
<code class="hljs avrasm has-numbering"> total_delta_time = (new_cpu<span class="hljs-preprocessor">.utime</span> + new_cpu<span class="hljs-preprocessor">.ntime</span> + new_cpu<span class="hljs-preprocessor">.stime</span> + new_cpu<span class="hljs-preprocessor">.itime</span> + new_cpu<span class="hljs-preprocessor">.iowtime</span> + new_cpu<span class="hljs-preprocessor">.irqtime</span> + new_cpu<span class="hljs-preprocessor">.sirqtime</span>) - (old_cpu<span class="hljs-preprocessor">.utime</span> + old_cpu<span class="hljs-preprocessor">.ntime</span> + old_cpu<span class="hljs-preprocessor">.stime</span> + old_cpu<span class="hljs-preprocessor">.itime</span> + old_cpu<span class="hljs-preprocessor">.iowtime</span> + old_cpu<span class="hljs-preprocessor">.irqtime</span> + old_cpu<span class="hljs-preprocessor">.sirqtime</span>)<span class="hljs-comment">;</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul>
而這些變數的值,是在read_procs通過讀取/proc/stat的jiffies得到:
<code class="hljs perl has-numbering">static void read_procs(void) { ... proc_dir = <span class="hljs-keyword">opendir</span>(<span class="hljs-string">"/proc"</span>); <span class="hljs-keyword">if</span> (!proc_dir) <span class="hljs-keyword">die</span>(<span class="hljs-string">"Could not open /proc.\n"</span>); new_procs = calloc(INIT_PROCS * (threads ? THREAD_MULT : <span class="hljs-number">1</span>), sizeof(struct proc_info <span class="hljs-variable">*)</span>); num_new_procs = INIT_PROCS * (threads ? THREAD_MULT : <span class="hljs-number">1</span>); file = fopen(<span class="hljs-string">"/proc/stat"</span>, <span class="hljs-string">"r"</span>); <span class="hljs-keyword">if</span> (!file) <span class="hljs-keyword">die</span>(<span class="hljs-string">"Could not open /proc/stat.\n"</span>); fscanf(file, <span class="hljs-string">"cpu <span class="hljs-variable">%lu</span> <span class="hljs-variable">%lu</span> <span class="hljs-variable">%lu</span> <span class="hljs-variable">%lu</span> <span class="hljs-variable">%lu</span> <span class="hljs-variable">%lu</span> <span class="hljs-variable">%lu</span>"</span>, &new_cpu.<span class="hljs-keyword">utime</span>, &new_cpu.ntime, &new_cpu.stime, &new_cpu.itime, &new_cpu.iowtime, &new_cpu.irqtime, &new_cpu.sirqtime); fclose(file);</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li></ul>
而proc->delta_time是兩次讀取/proc/pid/stat相減得到:
<code class="hljs haskell has-numbering"><span class="hljs-title">static</span> int read_stat(char *filename, struct proc_info *<span class="hljs-keyword">proc</span>) { ... /* <span class="hljs-type">Scan</span> rest <span class="hljs-keyword">of</span> string. */ sscanf(close_paren + <span class="hljs-number">1</span>, <span class="hljs-string">" %c "</span> <span class="hljs-string">"%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "</span> <span class="hljs-string">"%"</span> <span class="hljs-type">SCNu64</span> <span class="hljs-string">"%"</span> <span class="hljs-type">SCNu64</span> <span class="hljs-string">"%*d %*d %*d %*d %*d %*d %*d "</span> <span class="hljs-string">"%"</span> <span class="hljs-type">SCNu64</span> <span class="hljs-string">"%"</span> <span class="hljs-type">SCNu64</span> <span class="hljs-string">"%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "</span> <span class="hljs-string">"%d"</span>, &<span class="hljs-keyword">proc</span>->state, &<span class="hljs-keyword">proc</span>->utime, &<span class="hljs-keyword">proc</span>->stime, &<span class="hljs-keyword">proc</span>->vss, &<span class="hljs-keyword">proc</span>->rss, &<span class="hljs-keyword">proc</span>->prs); return <span class="hljs-number">0</span>; }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li></ul>
可見,top是一段時間內,計算process的cpu jiffies與總的cpu jiffies差值得到。
2、dump cpuinfo
dump cpuinfo是Android特有的命令(我一直都android的各種dump、trace非常感興趣,快玩物喪志了。。。)。dump cpuinfo命令的實現在androidm/frameworks/base/core/java/com/android/internal/os/ProcessCpuTracker.java類裡面,方法是printCurrentState:
<code class="hljs avrasm has-numbering">final public String printCurrentState(long now) { ... int N = mWorkingProcs<span class="hljs-preprocessor">.size</span>()<span class="hljs-comment">;</span> for (int i=<span class="hljs-number">0</span><span class="hljs-comment">; i<N; i++) {</span> Stats <span class="hljs-keyword">st</span> = mWorkingProcs<span class="hljs-preprocessor">.get</span>(i)<span class="hljs-comment">;</span> printProcessCPU(pw, <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.added</span> ? <span class="hljs-string">" +"</span> : (<span class="hljs-keyword">st</span><span class="hljs-preprocessor">.removed</span> ? <span class="hljs-string">" -"</span>: <span class="hljs-string">" "</span>), <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.pid</span>, <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.name</span>, (int)<span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_uptime, <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_utime, <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_stime, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_minfaults, <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_majfaults)<span class="hljs-comment">;</span> if (!<span class="hljs-keyword">st</span><span class="hljs-preprocessor">.removed</span> && <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.workingThreads</span> != null) { int M = <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.workingThreads</span><span class="hljs-preprocessor">.size</span>()<span class="hljs-comment">;</span> for (int j=<span class="hljs-number">0</span><span class="hljs-comment">; j<M; j++) {</span> Stats <span class="hljs-keyword">tst</span> = <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.workingThreads</span><span class="hljs-preprocessor">.get</span>(j)<span class="hljs-comment">;</span> printProcessCPU(pw, <span class="hljs-keyword">tst</span><span class="hljs-preprocessor">.added</span> ? <span class="hljs-string">" +"</span> : (<span class="hljs-keyword">tst</span><span class="hljs-preprocessor">.removed</span> ? <span class="hljs-string">" -"</span>: <span class="hljs-string">" "</span>), <span class="hljs-keyword">tst</span><span class="hljs-preprocessor">.pid</span>, <span class="hljs-keyword">tst</span><span class="hljs-preprocessor">.name</span>, (int)<span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_uptime, <span class="hljs-keyword">tst</span><span class="hljs-preprocessor">.rel</span>_utime, <span class="hljs-keyword">tst</span><span class="hljs-preprocessor">.rel</span>_stime, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>)<span class="hljs-comment">;</span> } } } ... }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li></ul>
而printProcessCPU輸出process CPU的使用情況:
<code class="hljs cs has-numbering"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printProcessCPU</span>(PrintWriter pw, String prefix, <span class="hljs-keyword">int</span> pid, String label, <span class="hljs-keyword">int</span> totalTime, <span class="hljs-keyword">int</span> user, <span class="hljs-keyword">int</span> system, <span class="hljs-keyword">int</span> iowait, <span class="hljs-keyword">int</span> irq, <span class="hljs-keyword">int</span> softIrq, <span class="hljs-keyword">int</span> minFaults, <span class="hljs-keyword">int</span> majFaults) { pw.print(prefix); <span class="hljs-keyword">if</span> (totalTime == <span class="hljs-number">0</span>) totalTime = <span class="hljs-number">1</span>; printRatio(pw, user+system+iowait+irq+softIrq, totalTime); ... }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li></ul>
user+system+iowait+irq+softIrq 比totalTime。
看下st個變數的賦值,在collectStats裡面:
<code class="hljs avrasm has-numbering">private int[] collectStats(String statsFile, int parentPid, boolean first, int[] curPids, ArrayList<Stats> allProcs) { int[] pids = Process<span class="hljs-preprocessor">.getPids</span>(statsFile, curPids)<span class="hljs-comment">;</span> ... final long uptime = SystemClock<span class="hljs-preprocessor">.uptimeMillis</span>()<span class="hljs-comment">;</span> final long[] procStats = mProcessStatsData<span class="hljs-comment">;</span> if (!Process<span class="hljs-preprocessor">.readProcFile</span>(<span class="hljs-keyword">st</span><span class="hljs-preprocessor">.statFile</span><span class="hljs-preprocessor">.toString</span>(), PROCESS_STATS_FORMAT, null, procStats, null)) { continue<span class="hljs-comment">;</span> } ... if (DEBUG) Slog<span class="hljs-preprocessor">.v</span>(<span class="hljs-string">"Load"</span>, <span class="hljs-string">"Stats changed "</span> + <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.name</span> + <span class="hljs-string">" pid="</span> + <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.pid</span> + <span class="hljs-string">" utime="</span> + utime + <span class="hljs-string">"-"</span> + <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_utime + <span class="hljs-string">" stime="</span> + stime + <span class="hljs-string">"-"</span> + <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_stime + <span class="hljs-string">" minfaults="</span> + minfaults + <span class="hljs-string">"-"</span> + <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_minfaults + <span class="hljs-string">" majfaults="</span> + majfaults + <span class="hljs-string">"-"</span> + <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_majfaults)<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_uptime = uptime - <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_uptime<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_uptime = uptime<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_utime = (int)(utime - <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_utime)<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_stime = (int)(stime - <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_stime)<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_utime = utime<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_stime = stime<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_minfaults = (int)(minfaults - <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_minfaults)<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.rel</span>_majfaults = (int)(majfaults - <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_majfaults)<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_minfaults = minfaults<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.base</span>_majfaults = majfaults<span class="hljs-comment">;</span> <span class="hljs-keyword">st</span><span class="hljs-preprocessor">.working</span> = true<span class="hljs-comment">;</span> ... }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li></ul>
st.rel_utime 和 st.rel_stime還是通過讀/proc/pid/stat相減得到,而st.rel_uptime卻是通過 SystemClock.uptimeMillis()差值,並不是跟top一樣,通過得到總CPU jiffies。
看到這,也就能明白,top跟dump cpuinfo的區別在於:top分母有的是總測CPU jiffies,而dump cpuinfo是uptime,是時間,而並非jiffies,也能解釋為什麼top出來的cpu,大部分時間會比dump cpuinfo的原因。
相關推薦
Android CPU使用率:top和dump cpuinfo的不同
CPU是系統非常重要的資源,在Android中,檢視CPU使用情況,可以使用top命令和dump cpuinfo。我記得很久以前,就發現這兩者存在不同,初步猜測應該是演算法上存在差異。最近需要採集應用CPU的使用率,看了一下兩種CPU的計算方法。 1、top top是比較經典的CPU計算方法,top的程式碼
Android 簡單案例:onSaveInstanceState 和 onRestoreInstanceState
ted bsp raw hand current div set for hot import android.app.Activity; import android.os.Bundle; import android.view.View; import android
查看系統cpu性能top和多核cpu使用性能
sta 情況 top 查看系統 系統 停止 排序。 性能 內存 1、使用top查看系統當前負載情況。 在顯示過程 按P會按照cpu使用率排序,按M會按照內存占用率排序。 2、多核CPU上,每個核的使用率,使用 mpstat mpstat -P ALL 1
android小知識:ArrayList和陣列之間的轉換
List----->陣列開發中不免碰到List與陣列型別之間的相互轉換,舉一個簡單的例子: package test.test1; import java.util.ArrayList; import java.util.List; public class Test { /** * @param ar
Android同步類:Mutex和Condition的使用方式
Metux類 Mutex是互斥類,多個執行緒訪問同一個資源時,要確保他們的互斥。主要函式有 lock(),unlock(),trylock() 函式名 作用 lock() 當使用lock函式時,當前的執行緒就會lock住;如
Android熱修復:Andfix和Hotfix,兩種方案的比較與實現
Andfix和hotfix是兩種android熱修復框架。 android的熱修復技術我看的最早的應該是QQ空間團隊的解決方案,後來真正需要了,才仔細調查,現在的方案中,阿里有兩種Dexposed和Andfix框架,由於前一種不支援5.0以上android系統
android gradle依賴:implementation 和compile的區別
可以看到在Android studio3.0中,compile依賴關係已被棄用,被implementation和api替代,provided被compile only替代,apk被runtime only替代。 我們先來看看implementation和a
APP性能(Android手機):內存和CPU
右上角 ref 技術分享 alt 看書 是否 對比測試 lease 性能 1 App性能測試 幀率大小影響頁面的流暢度。 不同機型測試時,會有差距,配置差的手機性能測試會差,不需要橫向比較。 同一個手機,對新老版本app進行對比測試,選擇配置比較
Android:ABI和CPU關係
轉載請標明出處:http://blog.csdn.net/xx326664162/article/details/51167849 文章出自:薛瑄的部落格 你也可以檢視我的其他同類文章,也會讓你有一定的收貨! 關於ABI的知識,我整理這兩篇部落格,相信會對你有幫助: ABI和CPU關係的
Android零基礎入門第39節:ListActivity和自定義列表項
arraylist component save 高速 ram 如果 view設置 ren 屬性 相信通過前兩期的學習,以及會開發最簡單的一些列表界面了吧,那麽本期接著來學習更多方法技巧。 一、使用ListActivity 如果程序的窗口僅僅需要
Android零基礎入門第55節:ImageSwitcher和TextSwitcher使用
dad arr 縮放 設置 cfa gen 通過 share man 上一期我們了解了ViewAnimator組件和ViewSwitcher組件的使用,你都掌握了嗎?本期一起來學習ViewSwitcher的兩個子組件ImageSwitcher和TextSwitche
linux查看 cpu及內存和硬盤使用情況的命令top
函數 移動 超過 命令執行過程 opp 次數 內存 快捷 所有者 使用時輸入 top,退出時輸入q http://www.cnblogs.com/ggjucheng/archive/2012/01/08/2316399.html 簡介 top命令是Linux下常用的性能分析
Android 比SwipeRefreshLayout更漂亮和強大的下拉刷新控件:Android-MaterialRefreshLayout
swipe app ant log functions done span simple list 這是一個下拉刷新的控件,它比SwipeRefreshLayout更加漂亮和強大。它易於使用並且支持API LEVEL >= 8。希望你能夠喜歡。 Now let me
Android項目實戰(六):JazzyGridView和JazzyListView的使用
@+ java類 gif HR 使用 out tar 項目 適配器 原文:Android項目實戰(六):JazzyGridView和JazzyListView的使用GridView和ListView控件劃動的動畫效果 ---------------------------
Android 訊息機制:Handler、MessageQueue 和 Looper
在這篇文章中,我們將會討論 Android 的訊息機制。提到 Handler,有過一些 Android 開發經驗的都應該很清楚它的作用,通常我們使用它來通知主執行緒更新 UI。但是 Handler 需要底層的 MessageQueue 和 Looper 來支援才能運作。這篇文章中,我們將會討論它們三個之間的關
Android開發(2):資料儲存之一:SharedPrefrences和檔案讀寫
一、資料儲存 本文主要講前兩種儲存方式,其中檔案讀寫只記錄Internal Storage方式 1. SharedPrefrences方式 輕量級NVP方式儲存,以XML的檔案方式儲存,適合少量資料的儲存。 NVP:Name/Value pair, 名稱/值 對。 2.
Android圖片壓縮的兩個開源庫:Luban和Compressor
Luban https://github.com/Curzibn/Luban Luban,也稱魯班。該庫作者一針見血的提出當前圖片壓縮處理的一些問題:單純對圖片進行裁切,壓縮已經有很多文章介紹。但是裁切成多少,壓縮成多少卻很難控制好,裁切過
Android進階:步驟四:Android螢幕和圖片的適配
修改:https://www.jianshu.com/p/759375113de9 一、碎片化 說起來,人們口中的 Android 碎片化主要表現在 Android 品牌和機型眾多,Android 版本眾多和 Android 裝置的尺寸和解析度眾多。也就是Android碎
【轉】Android開發:Service和Thread的關係
不少Android初學者都可能會有這樣的疑惑,Service和Thread到底有什麼關係呢?什麼時候應該用Service,什麼時候又應該用Thread?答案可能會有點讓你吃驚,因為Service和Thread之間沒有任何關係! 之所以有不少人會把它們聯絡起來,主要就是因為Service的後臺概念。Threa
【轉】Android開發:Service和Thread的關系
墨跡天氣 關系 https 依賴 and 但是 size nac 後臺運行 不少Android初學者都可能會有這樣的疑惑,Service和Thread到底有什麽關系呢?什麽時候應該用Service,什麽時候又應該用Thread?答案可能會有點讓你吃驚,因為Service和T