1 /**
2 * The minimum duration, in ms, for which the main thread has been b
locked. May be more.
3 */
4 public final long duration;
5 static ANRError NewMainOnly(long duration) {
6 // 1
、
获
取
主
线
程
的
堆
栈
信
息
7 final Thread mainThread = Looper.getMainLooper().getThread();
8 final StackTraceElement[] mainStackTrace = mainThread.getStackTr
ace();
9 // 2
、
返
回
⼀个
包
含
主
线
程
名
、
主
线
程
堆
栈
信
息
以
及发
⽣
ANR
的
最
⼩
时
间
值
的
实
例
。
10 return new ANRError(new $(getThreadTitle(mainThread), mainStackT
race).new _Thread(null), duration);
11 }
可
以
看
到
,
在
注
释
1
处
,
⾸
先
获
了主
线
程
的
堆
栈
信
息
,
然
后
返
回
了
⼀个
包
含
主
线
程
名
、
主
线
程
堆
栈
信
息
以
及
发
⽣
ANR
的
最
⼩
时
间
值
的
实
例
。
(
我
们
可
以
改
造
其
源
码
在
此
时
添
加
更
多
的
卡
顿
现
场
信
息
,
如
CPU
使
⽤率
和
调
度
信
息
、
内
存
相
关
信
息
、
I/O
和
⽹络
相
关
的
信
息
等等
)
接
下
来
,
我
们
再
回
到
ANRWatchDog
的
run
⽅
法
中
的
注
释
6
处
,
最
后
这
⾥
会
通过
ANRListener
调
⽤
它
的
onAppNotResponding
⽅
法
,
其
默
认
的
处
理
会
直
接
抛
出
当
前
的
ANRError
,
导
致
程
序
崩
溃
。
对
应
的
代
码
如
下
所
示
:
1 private static final ANRListener DEFAULT_ANR_LISTENER = new ANRListen
er() {
2 @Override public void onAppNotResponding(ANRError error) {
3 throw error;
4 }
5 };
了
解
了
ANRWatchDog
的
实
现
原
理
之
后
,
我
们
试
⼀
试
它
的
效
果
如
何
。
⾸
先
,
我
们
给
MainActivity
中
的
悬
浮
按
钮
添
加
主
线
程
休
眠
10s
的
代
码
,
如
下
所
示
:
1 @OnClick({R.id.main_floating_action_btn})
2 void onClick(View view) {
3 switch (view.getId()) {
4 case R.id.main_floating_action_btn:
5 try {
6 //
对
应
项
⽬
中
的
第
170
⾏
7 Thread.sleep(10000);
8 } catch (InterruptedException e) {