2

背景:

这个应用程序是一个简单的 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 个循环上更新,这意味着threadRefreshTextView 包含以下文本:“# Refreshed Times : 1”

4

1 回答 1

1

原来我没有陷入僵局,这是由于Intents.

原因:

我用的是一个Intent. 这创建了一个服务,该服务创建了一个PendingIntent(用于单击通知以重新打开应用程序),这锁定了我的 UI 线程。所以我上面的代码中没有任何东西影响/导致问题!

我是如何解决这个问题的:

使用日志。不是自定义日志,只是简单Log.i()

我记录了代码的每一部分:

  1. 从高水平开始,并努力寻找可能的原因。

  2. 如果这不起作用/产生结果,请查看您是否有任何其他类,在我的情况下是 ServiceClass,记录下来。

这是我发现我的代码没有进一步执行的地方,所以回溯到调用代码,我发现我使用了一个 Intent 等待意图完成后再继续,从而导致我的代码挂起。

解决方案:

应该使用的是用于服务的两种意图之一。

这些是经常被问到且有据可查的对象。StackOverflow 上有很多关于这两种意图类型区别的问题,这里这里有 2 个排名靠前的问题,还有一点UI 和服务问题

我将使用 IntentService。

希望这可以帮助!

于 2016-07-01T12:16:36.810 回答