阿里巴巴:- 给你一个 Demo- 你如何快速定位 ANR
protected void onProgressUpdate(Integer... progress) {setProgressPercent(progress[0]);}
// This is called when doInBackground() is finishedprotected void onPostExecute(Long result) {showNotification("Downloaded " + result + " bytes");}
2)如果你实现了 Thread 或者 HandlerThread,请确保你的 UI 线程不会因为等待工作线程的某个任务而去执行 Thread.wait()或者 Thread.sleep()。UI 线程不应该去等待工作线程完成某个任务,你的 UI 线程应该提供一个 Handler 给其他工作线程,这样工作线程能够通过这个 Handler 在任务结束的时候通知 UI 线程。例如:继承 Thread 类
new Thread(new Runnable() {@Overridepublic void run() {/**耗时操作/handler.post(new Runnable() {@Overridepublic void run() {/*更新 UI*/}});}}).start();
实现 Runnable 接口
class PrimeRun implements Runnable {long minPrime;PrimeRun(long minPrime) {this.minPrime = minPrime;}
public void run() {// compute primes larger than minPrime. . .}}
PrimeRun p = new PrimeRun(143);new Thread(p).start();
使用 HandlerThread
// 启动一个名为 new_thread 的子线程 HandlerThread thread = new HandlerThread("new_thread");thread.start();
// 取 new_thread 赋值给 ServiceHandlerprivate ServiceHandler mServiceHandler;mServiceLooper = thread.getLooper();mServiceHandler = new ServiceHandler(mServiceLooper);
private final class ServiceHandler extends Handler {public ServiceHandler(Looper looper) {super(looper);}
@Overridepublic void handleMessage(Message msg) {//默认 Handler 的 handleMessage 方法是运行在主线程中的,如果传入一个工作线程的 Looper,则改变 HandleMessage 方法执行的所在线程}}
3)开发在日常的开发过程中使用 Thread 或者 HandlerThread,可以尝试调用 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)设置较低的优先级,否则仍然会降低程序响应,因为默认 Thread 的优先级和主线程相同。
4)Activity 的 onCreate 和 onResume 回调中尽量避免耗时的代码,应该尽可能的做比较少的事情,其实,任何
执行在 UI 线程中的方法都应该尽可能简短快速。类似网络或者 DB 操作等可能长时间执行的操作,或者是类似调整 bitmap 大小等需要长时间计算的操作,都应该执行在工作线程中。
5)BroadcastReceiver 中 onReceive 代码也要尽量减少耗时。如果必须在 onReceive 方法中执行耗时操作,建议使用 IntentService 进行处理,IntentService 集开启线程和自动关闭服务两种功能于一身,本身非常灵活。
@Overridepublic void onReceive(Context context, Intent intent) {// This is a long-running operationBubbleSort.sort(data);}//上面的代码在 onReceive 方法中执行了耗时操作
@Overridepublic void onReceive(Context context, Intent intent) {// The task now runs on a worker thread.Intent intentService = new Intent(context, MyIntentService.class);context.startService(intentService);}
public class MyIntentService extends IntentService {@Overrideprotected void onHandleIntent(@Nullable Intent intent) {BubbleSort.sort(data);}}//将 onReceive 的耗时操作放入到 IntentService 中执行,执行完之后自动关闭工作线程
6)增加界面响应性(交互层面),这是一个成熟应用必备的标志—通常来说,100ms - 200ms 是用户能够察觉到卡顿的上限。如果你的程序在启动阶段有一个耗时的初始化操作,可以考虑显示一个闪屏,要么尽快的显示主界面,然后马上显示一个加载的对话框,异步加载数据。无论哪种情况,你都应该显示一个进度信息,以免用户感觉程序有卡顿的情况。##三、辅助处理 ANR 问题的工具 1.Traceview - 系统性能分析工具,用于定位应用代码中的耗时操作
①选好应用的进程,执行一段应用操作,从图中的上半部分,可以看到各个线程的各个方法的执行时间;
②从图中的下半部分,可以该段操作中具体调用的方法和每个方法的执行时间、执行次数。占 CPU 的百分比;
该图是具体的方法执行时间分布图,我们重点关注其中的“Incl Real Time”这一时间指标,其为方法的实际调用时间,单位毫秒,查看时点击 Incl Real Time 进行排列,方法会根据时间长短进行排列,其中超过 500ms 的方法我们都该重点关注。
2.Systrace - Android4.1 新增的应用性能数据采样和分析工具(与 google 引擎联合开发 使用时借助 chorme 浏览器)
连接手机,进行一段操作,系统会生成一份 Html 文件,在谷歌浏览器中打开,如图:
①Sytrace 会显示在这段操作期间所有的进程信息,在其中找到自己的进程,可以看到在测试进程中,我们定位 UI Thread,可以看到里面的系统方法,这是 UI 渲染时的调用方法,上面有一个个的圈,绿色圈代表帧渲染时间是 16.6ms(Android 系统渲染 UI 界面时间为 1 秒 60 帧,每帧即 16.6ms),超过该值的帧用红色圈标注;
评论