背景:
这个应用程序是一个简单的 Wifi 管理器,收集/扫描并在列表视图中显示结果。由于此扫描按间隔扫描,因此我创建了一个线程并在扫描之间设置了一个 Thread.sleep(interval) ,因此在处理完成后,它会休眠 X 毫秒。
我对我的代码进行了一些“更改”/更新,现在我的应用程序进入 ANR 状态并显示调试器消息"Signal Catcher"]: reacting to signal 3
完全错误:
07-01 10:14:16.772 10027-10034/com.cynetstudios.wifimanager I/art: Thread[2,tid=10034,WaitingInMainSignalCatcherLoop,Thread*=0xa9007000,peer=0x12d1a0a0,"Signal Catcher"]: reacting to signal 3
07-01 10:14:17.101 10027-10034/com.cynetstudios.wifimanager I/art: Wrote stack traces to '/data/anr/traces.txt'
问题:
添加权限之前:
在onCreate()
main 中,我有我的代码来启动我的扫描循环并开始输出数据,这有效并且按预期输出数据。
线程代码:
t = new Thread(new Runnable() {
public void run() {
while (!bStopThread) {
ThreadCounter++;
if (bSafe) {
initWiFiArrays(); //Scans and inserts data into lists
CreateSetAdapter(); //Converts lists into adapter, and sets adapter to ExpandableListView
threadRefresh.setText("# Refreshed Times : " + String.valueOf(ThreadCounter));
writeResultsToFile(); //Write results to file
} else
stopScan();
try {
Thread.sleep(scanInterval);
} catch (Exception x) {
x.printStackTrace();
}
}
}
});
t.start();
添加权限后:
在做了一些研究之后,我发现我应该Initiate scan
从 onCreate 中删除这个方法,因为它会阻塞任何线程调用,我将它添加到 onStart 并添加了一个RunOnUITHD(Runnable r)
仅访问 UI 以使用基本代码进行更新的方法。
新线程代码:
t = new Thread(new Runnable() {
public void run() {
while (!bStopThread) {
ThreadCounter++;
if (bSafe) {
initWiFiArrays();
CreateSetAdapter();
RunOnUITHD(new Runnable() {
@Override
public void run() {
threadRefresh.setText("# Refreshed Times : " + String.valueOf(ThreadCounter));
}
});
writeResultsToFile();
} else
stopScan();
try {
Thread.sleep(scanInterval);
} catch (Exception x) {
x.printStackTrace();
}
}
}
});
t.start();
处理程序定义为:handler = new Handler(context.getMainLooper());
RunOnUITHD
private void RunOnUITHD(Runnable runnable) {
handler.post(runnable);
}
我仍然收到 ANR(最新的 ANR Traces)而且我不知道,我不知道我做错了什么。
更新:
我记录了主线程代码的每一部分,它按预期运行,循环和休眠,但 UI 没有更新......
将日志记录代码添加到new Runnable()
我注意到以下内容:
向例如的 ThreadCounter 添加断点ThreadCounter==11
应导致 10 个“更新线程...”和“完成更新...”循环,如下面的代码所示。
RunOnUITHD(new Runnable() {
@Override
public void run() {
logm("POST HANDLER: updating Thread Refresh Text");
threadRefresh.setText("# Refreshed Times : " + String.valueOf(ThreadCounter));
logm("POST HANDLER: Finished update Thread Refresh Text");
}
});
相反,我只注意到日志中显示的 4 个循环。
运行进一步的测试,ThreadCounter==3
记录的循环 = 1,所有进一步的测试导致更新 setText 的 1 个记录循环。
由于此线程是通过checkPermissions()
my 中的自定义方法启动的@Override onStart()
,因此我显示了一条 toast 消息,然后是 checkPermissions
@Override
protected void onStart() {
super.onStart();
Toast.makeText(main.this, "Starting Service", Toast.LENGTH_SHORT).show();
logm("checking permissions in 'onStart'");
checkPermissions();
}
尽管进行了这些测试,但 Toast 消息显示(不会消失)并且 setText 在 1 个循环上更新,这意味着threadRefresh
TextView 包含以下文本:“# Refreshed Times : 1”