內存抖動是因爲短期內有大量對象進出新生區致使的,它伴隨着頻繁的GC。 gc會大量佔用ui線程和cpu資源,會致使app總體卡頓android
android profile 效果圖以下圖數組
Memory 中緩存
咱們能夠看到 上面的一溜白色垃圾桶。說明在大量的執行gc操做。用了一下子 手機就開始卡了bash
快速定位 還得使用ddms。莫慌 as裏面自帶了 Tools->Android->Android Device Monitor 而後進行以下操做app
而後咱們看以下圖片。 dom
不要慌。ide
中間紅框的就是咱們要分析的內容,看他良莠不齊的就是 內存抖動形成的。函數
而後咱們把紅框 內容放大。鼠標點住 而後往右拖動,就會變大,點擊 紅框上面的數字就會變小。工具
咱們將 抖動的地方 放大後。隨便點擊會出現下圖樣式學習
能夠看到這個粉色的拱門的 圖案。從它的左邊到右邊 表明 一個函數 消耗的時間。
咱們接下來 就快速定位有問題的代碼在哪裏
我就隨便的滑動了一下,而後 隨便的選中了一個, 而後下邊就展現了 我所選中的 函數方法。
這裏有一個細節
說明 onClick 的序號 大於onClick 調用的方法 的序號。小於 onClick 被調用的方法的序號。
若是咱們一直點擊Parent 下的方法就會找到 序號爲1 的方法
以下圖所示。
咱們找到了錯誤代碼在哪。那麼咱們就看一下 源代碼的樣子
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
imPrettySureSortingIsFree();
}
});
}
/**
*  排序後打印二維數組,一行行打印
*/
public void imPrettySureSortingIsFree() {
int dimension = 300;
int[][] lotsOfInts = new int[dimension][dimension];
Random randomGenerator = new Random();
for (int i = 0; i < lotsOfInts.length; i++) {
for (int j = 0; j < lotsOfInts[i].length; j++) {
lotsOfInts[i][j] = randomGenerator.nextInt();
}
}
for (int i = 0; i < lotsOfInts.length; i++) {
String rowAsStr = "";
//排序
int[] sorted = getSorted(lotsOfInts[i]);
//拼接打印
for (int j = 0; j < lotsOfInts[i].length; j++) {
rowAsStr += sorted[j];
if (j < (lotsOfInts[i].length - 1)) {
rowAsStr += ", ";
}
}
}
}
public int[] getSorted(int[] input) {
int[] clone = input.clone();
Arrays.sort(clone);
return clone;
}
}
複製代碼
發現 rowAsStr 對象在被不斷地建立。 咱們能夠把它優化一下
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
imPrettySureSortingIsFree();
}
});
}
/**
*  排序後打印二維數組,一行行打印
*/
public void imPrettySureSortingIsFree() {
int dimension = 300;
int[][] lotsOfInts = new int[dimension][dimension];
Random randomGenerator = new Random();
for (int i = 0; i < lotsOfInts.length; i++) {
for (int j = 0; j < lotsOfInts[i].length; j++) {
lotsOfInts[i][j] = randomGenerator.nextInt();
}
}
//優化之後
StringBuilder sb = new StringBuilder();
String rowAsStr = "";
for(int i = 0; i < lotsOfInts.length; i++) {
//清除上一行
sb.delete(0,rowAsStr.length());
//排序
int[] sorted = getSorted(lotsOfInts[i]);
//拼接打印
for (int j = 0; j < lotsOfInts[i].length; j++) {
// rowAsStr += sorted[j];
sb.append(sorted[j]);
if(j < (lotsOfInts[i].length - 1)){
// rowAsStr += ", ";
sb.append(", ");
}
}
rowAsStr = sb.toString();
Log.i("ricky", "Row " + i + ": " + rowAsStr);
}
}
public int[] getSorted(int[] input) {
int[] clone = input.clone();
Arrays.sort(clone);
return clone;
}
}
複製代碼
這樣就不會內存抖動了
能找到問題,這個問題就基本解決了。
下面是避免發生內存抖動的幾點建議:
分析面板 面板列名含義以下:
Name | 方法的詳細信息,包括包名和參數信息 |
---|---|
col 3 is | right-aligned |
col 2 is | centered |
zebra stripes | are neat |
Incl Cpu Time | Cpu執行該方法該方法及其子方法所花費的時間 |
Incl Cpu Time % | Cpu執行該方法該方法及其子方法所花費佔Cpu總執行時間的百分比 |
Excl Cpu Time | Cpu執行該方法所話費的時間 |
Excl Cpu Time % | Cpu執行該方法所話費的時間佔Cpu總時間的百分比 |
Incl Real Time | 該方法及其子方法執行所話費的實際時間,從執行該方法到結束一共花了多少時間 |
Incl Real Time % | 上述時間佔總的運行時間的百分比 |
Excl Real Time % | 該方法自身的實際容許時間 |
Excl Real Time | 上述時間佔總的容許時間的百分比 |
Calls+Recur | 調用次數+遞歸次數,只在方法中顯示,在子展開後的父類和子類方法這一欄被下面的數據代替 |
Calls/Total | 調用次數和總次數的佔比 |
Cpu Time/Call | Cpu執行時間和調用次數的百分比,表明該函數消耗cpu的平均時間 |
Real Time/Call | 實際時間於調用次數的百分比,該表該函數平均執行時間 |
https://www.youtube.com/watch?v=McAvq5SkeTk