From a2053dd825f3e807f54a69a4edd2d214513a9840 Mon Sep 17 00:00:00 2001 From: Near Date: Wed, 14 Jun 2017 19:09:21 +0800 Subject: [PATCH] =?UTF-8?q?[dev]=20AndroidPerformanceMonitor=E6=BA=90?= =?UTF-8?q?=E7=A0=81=E7=AC=94=E8=AE=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blockcanary-analyzer/build.gradle | 1 + .../moduth/blockcanary/AbstractSampler.java | 2 +- .../blockcanary/BlockCanaryInternals.java | 32 ++++++++++------- .../github/moduth/blockcanary/CpuSampler.java | 9 ++--- .../blockcanary/HandlerThreadFactory.java | 2 +- .../github/moduth/blockcanary/LogWriter.java | 4 ++- .../moduth/blockcanary/LooperMonitor.java | 10 +++--- .../moduth/blockcanary/StackSampler.java | 2 ++ .../blockcanary/internal/BlockInfo.java | 1 + .../internal/PerformanceUtils.java | 8 ++--- .../blockcanary/internal/ProcessUtils.java | 2 +- blockcanary-android-no-op/build.gradle | 1 + blockcanary-android/build.gradle | 5 +-- .../moduth/blockcanary/BlockCanary.java | 9 +++-- .../moduth/blockcanary/DisplayService.java | 3 +- .../github/moduth/blockcanary/Uploader.java | 2 +- .../blockcanary/ui/BlockCanaryUtils.java | 7 ++-- .../blockcanary/ui/DisplayActivity.java | 35 ++++++++++++------- blockcanary-sample/build.gradle | 1 + build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +-- 21 files changed, 88 insertions(+), 54 deletions(-) diff --git a/blockcanary-analyzer/build.gradle b/blockcanary-analyzer/build.gradle index 83af379..96606f5 100644 --- a/blockcanary-analyzer/build.gradle +++ b/blockcanary-analyzer/build.gradle @@ -17,6 +17,7 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + buildToolsVersion '25.0.3' } dependencies { diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/AbstractSampler.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/AbstractSampler.java index c1e3383..5f40b08 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/AbstractSampler.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/AbstractSampler.java @@ -27,7 +27,7 @@ abstract class AbstractSampler { protected AtomicBoolean mShouldSample = new AtomicBoolean(false); protected long mSampleInterval; - private Runnable mRunnable = new Runnable() { + private Runnable mRunnable = new Runnable() {/*在子线程中定时取样*/ @Override public void run() { doSample(); diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockCanaryInternals.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockCanaryInternals.java index 3a0b859..1a3743f 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockCanaryInternals.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockCanaryInternals.java @@ -37,20 +37,24 @@ public final class BlockCanaryInternals { private List mInterceptorChain = new LinkedList<>(); - public BlockCanaryInternals() { + // TODO: 2017/3/3 BlockCanaryInternals构造函数 (4) + public BlockCanaryInternals() {/*初始化*/ - stackSampler = new StackSampler( + stackSampler = new StackSampler(/*堆栈数据Sampler*/ Looper.getMainLooper().getThread(), sContext.provideDumpInterval()); - cpuSampler = new CpuSampler(sContext.provideDumpInterval()); + cpuSampler = new CpuSampler(sContext.provideDumpInterval());/*Cpu数据Sampler*/ + /*设置自定义Printer,打印Looper dispatchMessage(msg)前后的时间*/ setMonitor(new LooperMonitor(new LooperMonitor.BlockListener() { + // TODO: 2017/3/3 卡顿时间超过设置:触发线程卡顿回调 (9) @Override public void onBlockEvent(long realTimeStart, long realTimeEnd, - long threadTimeStart, long threadTimeEnd) { + long threadTimeStart, long threadTimeEnd) {/*当页面卡顿时回调*/ // Get recent thread-stack entries and cpu usage + /*获取最新显存堆栈信息及Cpu使用情况*/ ArrayList threadStackEntries = stackSampler .getThreadStackEntries(realTimeStart, realTimeEnd); if (!threadStackEntries.isEmpty()) { @@ -60,10 +64,11 @@ public void onBlockEvent(long realTimeStart, long realTimeEnd, .setRecentCpuRate(cpuSampler.getCpuRateInfo()) .setThreadStackEntries(threadStackEntries) .flushString(); - LogWriter.save(blockInfo.toString()); + LogWriter.save(blockInfo.toString());/*保存卡顿信息*/ - if (mInterceptorChain.size() != 0) { + if (mInterceptorChain.size() != 0) {/*检查拦截器*/ for (BlockInterceptor interceptor : mInterceptorChain) { + // TODO: 2017/3/3 通知DisplayService等监听,弹出Notification提示出现线程卡顿 (12) interceptor.onBlock(getContext().provideContext(), blockInfo); } } @@ -71,7 +76,7 @@ public void onBlockEvent(long realTimeStart, long realTimeEnd, } }, getContext().provideBlockThreshold())); - LogWriter.cleanObsolete(); + LogWriter.cleanObsolete();/*重置过期数据*/ } /** @@ -79,6 +84,7 @@ public void onBlockEvent(long realTimeStart, long realTimeEnd, * * @return BlockCanaryInternals instance */ + // TODO: 2017/3/3 初始化BlockCanaryInternals (3) static BlockCanaryInternals getInstance() { if (sInstance == null) { synchronized (BlockCanaryInternals.class) { @@ -102,19 +108,19 @@ public static void setContext(BlockCanaryContext context) { public static BlockCanaryContext getContext() { return sContext; } - + /*添加拦截器*/ void addBlockInterceptor(BlockInterceptor blockInterceptor) { mInterceptorChain.add(blockInterceptor); } - + /*设置自定义Printer*/ private void setMonitor(LooperMonitor looperPrinter) { monitor = looperPrinter; } - + /*取样间隔*/ long getSampleDelay() { return (long) (BlockCanaryInternals.getContext().provideBlockThreshold() * 0.8f); } - + /*数据保存路径*/ static String getPath() { String state = Environment.getExternalStorageState(); String logPath = BlockCanaryInternals.getContext() @@ -126,7 +132,7 @@ static String getPath() { } return Environment.getDataDirectory().getAbsolutePath() + BlockCanaryInternals.getContext().providePath(); } - + /*创建文件夹*/ static File detectedBlockDirectory() { File directory = new File(getPath()); if (!directory.exists()) { @@ -134,7 +140,7 @@ static File detectedBlockDirectory() { } return directory; } - + /*获取所有Log文件*/ public static File[] getLogFiles() { File f = detectedBlockDirectory(); if (f.exists() && f.isDirectory()) { diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/CpuSampler.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/CpuSampler.java index 86c966d..24b3d97 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/CpuSampler.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/CpuSampler.java @@ -62,7 +62,7 @@ public void start() { /** * Get cpu rate information - * + * 获取cpu数据 * @return string show cpu rate information */ public String getCpuRateInfo() { @@ -78,7 +78,7 @@ public String getCpuRateInfo() { } return sb.toString(); } - + /*检测Cpu使用是否繁忙*/ public boolean isCpuBusy(long start, long end) { if (end - start > mSampleInterval) { long s = start - mSampleInterval; @@ -104,7 +104,7 @@ protected void doSample() { BufferedReader cpuReader = null; BufferedReader pidReader = null; - try { + try {/*获取Cpu使用信息*/ cpuReader = new BufferedReader(new InputStreamReader( new FileInputStream("/proc/stat")), BUFFER_SIZE); String cpuRate = cpuReader.readLine(); @@ -115,6 +115,7 @@ protected void doSample() { if (mPid == 0) { mPid = android.os.Process.myPid(); } + /*获取当前进程的Cpu使用信息*/ pidReader = new BufferedReader(new InputStreamReader( new FileInputStream("/proc/" + mPid + "/stat")), BUFFER_SIZE); String pidCpuRate = pidReader.readLine(); @@ -147,7 +148,7 @@ private void reset() { mTotalLast = 0; mAppCpuTimeLast = 0; } - + /*解析系统cpu及进程cpu使用信息*/ private void parse(String cpuRate, String pidCpuRate) { String[] cpuInfoArray = cpuRate.split(" "); if (cpuInfoArray.length < 9) { diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/HandlerThreadFactory.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/HandlerThreadFactory.java index bf4c26d..a3abbf2 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/HandlerThreadFactory.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/HandlerThreadFactory.java @@ -17,7 +17,7 @@ import android.os.Handler; import android.os.HandlerThread; - +/*Handler工厂*/ final class HandlerThreadFactory { private static HandlerThreadWrapper sLoopThread = new HandlerThreadWrapper("loop"); diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/LogWriter.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/LogWriter.java index fab8b72..f447570 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/LogWriter.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/LogWriter.java @@ -50,6 +50,7 @@ private LogWriter() { * @param str block info string * @return log file path */ + // TODO: 2017/3/3 保存卡顿数据 (11) public static String save(String str) { String path; synchronized (SAVE_DELETE_LOCK) { @@ -60,6 +61,7 @@ public static String save(String str) { /** * Delete obsolete log files, which is by default 2 days. + * 删除过期数据 */ public static void cleanObsolete() { HandlerThreadFactory.getWriteLogThreadHandler().post(new Runnable() { @@ -94,7 +96,7 @@ public static void deleteAll() { } } } - + /*保存卡顿log数据*/ private static String save(String logFileName, String str) { String path = ""; BufferedWriter writer = null; diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/LooperMonitor.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/LooperMonitor.java index b3dfb43..537b3d0 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/LooperMonitor.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/LooperMonitor.java @@ -17,7 +17,7 @@ import android.os.SystemClock; import android.util.Printer; - +/*自定义Printer*/ class LooperMonitor implements Printer { private static final int DEFAULT_BLOCK_THRESHOLD_MILLIS = 3000; @@ -43,17 +43,18 @@ public LooperMonitor(BlockListener blockListener, long blockThresholdMillis) { mBlockThresholdMillis = blockThresholdMillis; } + // TODO: 2017/3/3 重新Printer的println方法,监听Message Loop,同时记录该时间间隔的调用栈及CPU占用数据(6) @Override public void println(String x) { - if (!mPrintingStarted) { + if (!mPrintingStarted) {/*记录println message 时当前时间,同时开始dump 堆栈及cpu数据*/ mStartTimestamp = System.currentTimeMillis(); mStartThreadTimestamp = SystemClock.currentThreadTimeMillis(); mPrintingStarted = true; startDump(); - } else { + } else {/*记录end time ,停止dump 堆栈及cpu数据*/ final long endTime = System.currentTimeMillis(); mPrintingStarted = false; - if (isBlock(endTime)) { + if (isBlock(endTime)) {/*isBlock 回调监听*/// TODO: 2017/3/3 触发线程卡顿 (7) notifyBlockEvent(endTime); } stopDump(); @@ -64,6 +65,7 @@ private boolean isBlock(long endTime) { return endTime - mStartTimestamp > mBlockThresholdMillis; } + // TODO: 2017/3/3 卡顿时间超过设置:触发线程卡顿 (8) private void notifyBlockEvent(final long endTime) { final long startTime = mStartTimestamp; final long startThreadTime = mStartThreadTimestamp; diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/StackSampler.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/StackSampler.java index 2d65e4a..4f772cf 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/StackSampler.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/StackSampler.java @@ -41,6 +41,7 @@ public StackSampler(Thread thread, int maxEntryCount, long sampleIntervalMillis) mMaxEntryCount = maxEntryCount; } + // TODO: 2017/3/3 获取某个时间间隔内的线程调用栈数据 (10) public ArrayList getThreadStackEntries(long startTime, long endTime) { ArrayList result = new ArrayList<>(); synchronized (sStackMap) { @@ -58,6 +59,7 @@ public ArrayList getThreadStackEntries(long startTime, long endTime) { @Override protected void doSample() { + /*定时取样,获取当前主线程的堆栈信息*/ StringBuilder stringBuilder = new StringBuilder(); for (StackTraceElement stackTraceElement : mCurrentThread.getStackTrace()) { diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/BlockInfo.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/BlockInfo.java index 1b07edd..5c16324 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/BlockInfo.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/BlockInfo.java @@ -30,6 +30,7 @@ /** * Information to trace a block. + * 实体类 */ public class BlockInfo { diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/PerformanceUtils.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/PerformanceUtils.java index 1efecfa..c5e64b5 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/PerformanceUtils.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/PerformanceUtils.java @@ -27,7 +27,7 @@ import java.io.FileReader; import java.io.IOException; import java.util.regex.Pattern; - +/*性能工具类*/ class PerformanceUtils { private static final String TAG = "PerformanceUtils"; @@ -40,7 +40,7 @@ private PerformanceUtils() { /** * Get cpu core number - * + * 获取cpu内核数 * @return int cpu core number */ public static int getNumCores() { @@ -66,14 +66,14 @@ public boolean accept(File pathname) { } return sCoreNum; } - + /*获取空闲存储空间*/ public static long getFreeMemory() { ActivityManager am = (ActivityManager) BlockCanaryInternals.getContext().provideContext().getSystemService(Context.ACTIVITY_SERVICE); ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo(); am.getMemoryInfo(mi); return mi.availMem / 1024; } - + /*获取总存储空间*/ public static long getTotalMemory() { if (sTotalMemo == 0) { String str1 = "/proc/meminfo"; diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/ProcessUtils.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/ProcessUtils.java index 7029f0f..94c5a00 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/ProcessUtils.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/ProcessUtils.java @@ -21,7 +21,7 @@ import com.github.moduth.blockcanary.BlockCanaryInternals; import java.util.List; - +/*进程工具类*/ public class ProcessUtils { private static volatile String sProcessName; diff --git a/blockcanary-android-no-op/build.gradle b/blockcanary-android-no-op/build.gradle index 83af379..96606f5 100644 --- a/blockcanary-android-no-op/build.gradle +++ b/blockcanary-android-no-op/build.gradle @@ -17,6 +17,7 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + buildToolsVersion '25.0.3' } dependencies { diff --git a/blockcanary-android/build.gradle b/blockcanary-android/build.gradle index ac38b96..72bfaf7 100644 --- a/blockcanary-android/build.gradle +++ b/blockcanary-android/build.gradle @@ -17,10 +17,11 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + buildToolsVersion '25.0.3' } dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') -// compile project(':blockcanary-analyzer') - compile 'com.github.markzhai:blockcanary-analyzer:1.4.1' + compile project(':blockcanary-analyzer') +// compile 'com.github.markzhai:blockcanary-analyzer:1.4.1' } diff --git a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/BlockCanary.java b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/BlockCanary.java index edc0858..ad84322 100644 --- a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/BlockCanary.java +++ b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/BlockCanary.java @@ -38,7 +38,8 @@ public final class BlockCanary { private BlockCanaryInternals mBlockCanaryCore; private boolean mMonitorStarted = false; - private BlockCanary() { + // TODO: 2017/3/3 BlockCanary 构造函数 (2) + private BlockCanary() {/*初始化*/ BlockCanaryInternals.setContext(BlockCanaryContext.get()); mBlockCanaryCore = BlockCanaryInternals.getInstance(); mBlockCanaryCore.addBlockInterceptor(BlockCanaryContext.get()); @@ -56,8 +57,10 @@ private BlockCanary() { * @param blockCanaryContext BlockCanary context * @return {@link BlockCanary} */ + // TODO: 2017/3/3 BlockCanary (1) public static BlockCanary install(Context context, BlockCanaryContext blockCanaryContext) { BlockCanaryContext.init(context, blockCanaryContext); + /*设置以组件的形式DisplayActivity 是否有效*/ setEnabled(context, DisplayActivity.class, BlockCanaryContext.get().displayNotification()); return get(); } @@ -81,6 +84,7 @@ public static BlockCanary get() { /** * Start monitoring. */ + // TODO: 2017/3/3 设置自定义Printer,监听Message Loop(5) public void start() { if (!mMonitorStarted) { mMonitorStarted = true; @@ -134,6 +138,7 @@ public boolean isMonitorDurationEnd() { // these lines are originally copied from LeakCanary: Copyright (C) 2015 Square, Inc. private static final Executor fileIoExecutor = newSingleThreadExecutor("File-IO"); + /*在子线程中开启/禁用四大组件*/ private static void setEnabledBlocking(Context appContext, Class componentClass, boolean enabled) { @@ -157,7 +162,7 @@ private static void setEnabled(Context context, final Class componentClass, final boolean enabled) { final Context appContext = context.getApplicationContext(); - executeOnFileIoThread(new Runnable() { + executeOnFileIoThread(new Runnable() {/*在子线程中开启/禁用DisplayActivity 组件*/ @Override public void run() { setEnabledBlocking(appContext, componentClass, enabled); diff --git a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/DisplayService.java b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/DisplayService.java index 7d71590..8dcb322 100644 --- a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/DisplayService.java +++ b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/DisplayService.java @@ -38,6 +38,7 @@ final class DisplayService implements BlockInterceptor { private static final String TAG = "DisplayService"; + // TODO: 2017/3/3 弹出Notification提示出现线程卡顿 (13) @Override public void onBlock(Context context, BlockInfo blockInfo) { Intent intent = new Intent(context, DisplayActivity.class); @@ -55,7 +56,7 @@ private void show(Context context, String contentTitle, String contentText, Pend context.getSystemService(Context.NOTIFICATION_SERVICE); Notification notification; - if (SDK_INT < HONEYCOMB) { + if (SDK_INT < HONEYCOMB) {/*低于11的版本,通过反射setLatestEventInfo创建Notification*/ notification = new Notification(); notification.icon = R.drawable.block_canary_notification; notification.when = System.currentTimeMillis(); diff --git a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/Uploader.java b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/Uploader.java index 7334075..be57953 100644 --- a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/Uploader.java +++ b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/Uploader.java @@ -22,7 +22,7 @@ import java.util.Date; import java.util.Locale; - +/*文件上传类*/ final class Uploader { private static final String TAG = "Uploader"; diff --git a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/BlockCanaryUtils.java b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/BlockCanaryUtils.java index 195b0ce..6b9ae45 100644 --- a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/BlockCanaryUtils.java +++ b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/BlockCanaryUtils.java @@ -44,13 +44,13 @@ public static String concernStackString(BlockInfo blockInfo) { } return result; } - + /*判断数据是否有效*/ public static boolean isBlockInfoValid(BlockInfo blockInfo) { boolean isValid = !TextUtils.isEmpty(blockInfo.timeStart); isValid = isValid && blockInfo.timeCost >= 0; return isValid; } - + /*判断是否在白名单*/ public static boolean isInWhiteList(BlockInfo info) { for (String stackEntry : info.threadStackEntries) { if (Character.isLetter(stackEntry.charAt(0))) { @@ -71,6 +71,7 @@ public static List getConcernPackages() { return CONCERN_LIST; } + /*关注的堆栈信息*/ private static String concernStackString(String line) { for (String concernPackage : CONCERN_LIST) { if (line.startsWith(concernPackage)) { @@ -79,7 +80,7 @@ private static String concernStackString(String line) { } return null; } - + /*堆栈数据类名*/ private static String classSimpleName(String stackLine) { int index1 = stackLine.indexOf('('); int index2 = stackLine.indexOf(')'); diff --git a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DisplayActivity.java b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DisplayActivity.java index cdd30b8..6504a31 100644 --- a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DisplayActivity.java +++ b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DisplayActivity.java @@ -208,7 +208,7 @@ private void shareHeapDump(BlockInfoEx blockInfo) { intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(heapDumpFile)); startActivity(Intent.createChooser(intent, getString(R.string.block_canary_share_with))); } - + /*更新UI*/ private void updateUi() { final BlockInfoEx blockInfo = getBlock(mBlockStartTime); if (blockInfo == null) { @@ -220,12 +220,13 @@ private void updateUi() { mFailureView.setVisibility(GONE); if (blockInfo != null) { - renderBlockDetail(blockInfo); + renderBlockDetail(blockInfo);/**/ } else { renderBlockList(); } } + /*渲染Block List页面数据*/ private void renderBlockList() { ListAdapter listAdapter = mListView.getAdapter(); if (listAdapter instanceof BlockListAdapter) { @@ -237,21 +238,23 @@ private void renderBlockList() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { mBlockStartTime = mBlockInfoEntries.get(position).timeStart; - updateUi(); + updateUi();/*更新页面UI,显示Detail页面*/ } }); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - invalidateOptionsMenu(); + invalidateOptionsMenu();/*隐藏返回按钮*/ ActionBar actionBar = getActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(false); } } + /*设置Title*/ setTitle(getString(R.string.block_canary_block_list_title, getPackageName())); mActionButton.setText(R.string.block_canary_delete_all); mActionButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + /*删除卡顿Log*/ DialogInterface.OnClickListener okListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { @@ -273,6 +276,7 @@ public void onClick(DialogInterface dialogInterface, int i) { mActionButton.setVisibility(mBlockInfoEntries.isEmpty() ? GONE : VISIBLE); } + /*渲染Detail页面*/ private void renderBlockDetail(final BlockInfoEx blockInfo) { ListAdapter listAdapter = mListView.getAdapter(); final DetailAdapter adapter; @@ -284,11 +288,11 @@ private void renderBlockDetail(final BlockInfoEx blockInfo) { mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { - adapter.toggleRow(position); + adapter.toggleRow(position);/*展开或收缩item*/ } }); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - invalidateOptionsMenu(); + invalidateOptionsMenu();/*显示返回按钮*/ ActionBar actionBar = getActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); @@ -308,15 +312,16 @@ public void onClick(View v) { } } }); - adapter.update(blockInfo); + adapter.update(blockInfo);/*更新数据*/ setTitle(getString(R.string.block_canary_class_has_blocked, blockInfo.timeCost)); } + /*获取卡顿数据*/ private BlockInfoEx getBlock(String startTime) { if (mBlockInfoEntries == null || TextUtils.isEmpty(startTime)) { return null; } - for (BlockInfoEx blockInfo : mBlockInfoEntries) { + for (BlockInfoEx blockInfo : mBlockInfoEntries) {/*获取卡顿数据*/ if (blockInfo.timeStart != null && startTime.equals(blockInfo.timeStart)) { return blockInfo; } @@ -324,6 +329,7 @@ private BlockInfoEx getBlock(String startTime) { return null; } + /*自定义Adapter*/ class BlockListAdapter extends BaseAdapter { @Override @@ -369,6 +375,7 @@ public View getView(int position, View convertView, ViewGroup parent) { } } + /*加载卡顿数据*/ static class LoadBlocks implements Runnable { static final List inFlight = new ArrayList<>(); @@ -397,18 +404,18 @@ static void forgetActivity() { @Override public void run() { final List blockInfoList = new ArrayList<>(); - File[] files = BlockCanaryInternals.getLogFiles(); + File[] files = BlockCanaryInternals.getLogFiles();/*获取卡顿Log数据*/ if (files != null) { for (File blockFile : files) { try { BlockInfoEx blockInfo = BlockInfoEx.newInstance(blockFile); - if (!BlockCanaryUtils.isBlockInfoValid(blockInfo)) { + if (!BlockCanaryUtils.isBlockInfoValid(blockInfo)) {/*判断卡顿Log数据是否有效*/ throw new BlockInfoCorruptException(blockInfo); } boolean needAddToList = true; - if (BlockCanaryUtils.isInWhiteList(blockInfo)) { + if (BlockCanaryUtils.isInWhiteList(blockInfo)) {/*判断是否在白名单*/ if (BlockCanaryContext.get().deleteFilesInWhiteList()) { blockFile.delete(); blockFile = null; @@ -416,13 +423,13 @@ public void run() { needAddToList = false; } - blockInfo.concernStackString = BlockCanaryUtils.concernStackString(blockInfo); + blockInfo.concernStackString = BlockCanaryUtils.concernStackString(blockInfo);/*判断是否有需要关注的堆栈信息*/ if (BlockCanaryContext.get().filterNonConcernStack() && TextUtils.isEmpty(blockInfo.concernStackString)) { needAddToList = false; } - if (needAddToList && blockFile != null) { + if (needAddToList && blockFile != null) {/*添加到数据中*/ blockInfoList.add(blockInfo); } } catch (Exception e) { @@ -431,6 +438,7 @@ public void run() { Log.e(TAG, "Could not read block log file, deleted :" + blockFile, e); } } + /*数据按日期排序*/ Collections.sort(blockInfoList, new Comparator() { @Override public int compare(BlockInfoEx lhs, BlockInfoEx rhs) { @@ -439,6 +447,7 @@ public int compare(BlockInfoEx lhs, BlockInfoEx rhs) { } }); } + /*更新UI*/ mainHandler.post(new Runnable() { @Override public void run() { diff --git a/blockcanary-sample/build.gradle b/blockcanary-sample/build.gradle index 32d69b8..9b4d78e 100644 --- a/blockcanary-sample/build.gradle +++ b/blockcanary-sample/build.gradle @@ -17,6 +17,7 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + buildToolsVersion '25.0.3' } dependencies { diff --git a/build.gradle b/build.gradle index 2e498be..a2f6657 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.2' + classpath 'com.android.tools.build:gradle:2.3.2' } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 586936a..05972db 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Apr 13 16:42:11 CST 2016 +#Wed Jun 14 17:29:06 CST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip