线程无法访问视图 - Android

发布于 2024-12-18 08:49:41 字数 4738 浏览 2 评论 0原文

我正在编写一个手电筒应用程序,它是任何没有手电筒的手机的“屏幕灯”。我想要一个启用频闪灯功能的设置。然而,对于这种类型的“手电筒”,我认为最简单的方法是更改​​视图的背景。我在单独的线程中执行此操作,因为我使用 SeekBar 来获取频闪灯应闪烁的速度。但是,我不断收到线程无法访问视图的错误,因为它不是创建它的线程。有什么建议吗?

以下是 onCreate() 中包含的内容:

        mSeekBar = (SeekBar) findViewById(R.id.seekBar);
        mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
          public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {

                final Thread strober = new Thread(new Runnable(){
                    public void run(){
                        strobeLight();
                    }
                });             
                if (mSeekBar.getProgress()>0) {
                    runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        strober.start();
                    }
                    });
                }
                else {
                    runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        strober.interrupt();
                        relLayout.setBackgroundColor(color.all_white);
                    }
                    });
                }
          }
          public void onStartTrackingTouch(SeekBar seekBar) {}
          public void onStopTrackingTouch(SeekBar seekBar) {}          
        }); 

这是 strobeLight() 方法:

public void strobeLight(){
    boolean lightIsOn=true;

    runOnUiThread(new Runnable() {
    @Override
    public void run() { 
            do {
                    if (lightIsOn){
                        relLayout.setBackgroundColor(color.all_black);
                        try { Thread.sleep(1000/(mSeekBar.getProgress()+2)); }
                            catch (InterruptedException e) {}
                        lightIsOn=false; 
                        strobeActivated=true;}
                    else{
                        relLayout.setBackgroundColor(color.all_white);  
                        try { Thread.sleep(1000/(mSeekBar.getProgress()+2)); }
                            catch (InterruptedException e) {}                       
                        lightIsOn=true; }
                    if (mSeekBar.getProgress()<1)
                        strobeActivated=false;
            } while (strobeActivated);
            relLayout.setBackgroundColor(color.all_white);
    }
});   
}   

以下是上述代码的 LogCat:

11-28 17:17:58.383: E/ActivityManager(16877): ANR in com.marshall.meadows182 (com.marshall.meadows182/.LightNoTorch),  time=603431510
11-28 17:17:58.383: E/ActivityManager(16877): Reason: keyDispatchingTimedOut
11-28 17:17:58.383: E/ActivityManager(16877): Load: 1.53 / 1.62 / 1.62
11-28 17:17:58.383: E/ActivityManager(16877): CPU usage from 14662ms to 0ms ago:
11-28 17:17:58.383: E/ActivityManager(16877):   0.8% 16877/system_server: 0.4% user + 0.4% kernel / faults: 7 minor
11-28 17:17:58.383: E/ActivityManager(16877):   0% 14673/com.qikffc.android: 0% user + 0% kernel / faults: 151 minor
11-28 17:17:58.383: E/ActivityManager(16877):   0.2% 16957/com.android.systemui: 0.2% user + 0% kernel / faults: 1 minor
11-28 17:17:58.383: E/ActivityManager(16877):   0.1% 16999/com.android.phone: 0% user + 0% kernel
11-28 17:17:58.383: E/ActivityManager(16877):   0.1% 13/kondemand/0: 0% user + 0.1% kernel
11-28 17:17:58.383: E/ActivityManager(16877):   0% 68/rild: 0% user + 0% kernel / faults: 6 minor
11-28 17:17:58.383: E/ActivityManager(16877):   0% 14830/logcat: 0% user + 0% kernel
11-28 17:17:58.383: E/ActivityManager(16877):   0.1% 14868/com.marshall.meadows182: 0% user + 0% kernel / faults: 9 minor
11-28 17:17:58.383: E/ActivityManager(16877):   0% 24825/adbd: 0% user + 0% kernel
11-28 17:17:58.383: E/ActivityManager(16877):   0% 5446/com.google.android.apps.maps:NetworkLocationService: 0% user + 0% kernel
11-28 17:17:58.383: E/ActivityManager(16877):   0% 7839/wpa_supplicant: 0% user + 0% kernel / faults: 3 minor
11-28 17:17:58.383: E/ActivityManager(16877):   0% 17054/com.google.process.gapps: 0% user + 0% kernel / faults: 4 minor
11-28 17:17:58.383: E/ActivityManager(16877):   0% 25055/iqd: 0% user + 0% kernel
11-28 17:17:58.383: E/ActivityManager(16877): 2.7% TOTAL: 1.8% user + 0.8% kernel
11-28 17:17:58.383: E/ActivityManager(16877): CPU usage from 416ms to 935ms later with 99% awake:
11-28 17:17:58.383: E/ActivityManager(16877):   7.4% 16877/system_server: 0% user + 7.4% kernel / faults: 6 minor
11-28 17:17:58.383: E/ActivityManager(16877):     9.2% 16923/InputDispatcher: 1.8% user + 7.4% kernel
11-28 17:17:58.383: E/ActivityManager(16877): 3.8% TOTAL: 0% user + 3.8% kernel

I am writing a flashlight app that is a "screen light" for any phone without a torch. I want to have a setting that enables a Strobe Light feature. However, with this type of "flashlight" I thought the easiest way to do this, would be to change the background of the view. I do this in a separate thread because I use a SeekBar to get how fast the strobelight should flash. However, I keep getting the error that the Thread cannot access the View because it is not the Thread that created it. Any suggestions?

Here is what is contained within the onCreate():

        mSeekBar = (SeekBar) findViewById(R.id.seekBar);
        mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
          public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {

                final Thread strober = new Thread(new Runnable(){
                    public void run(){
                        strobeLight();
                    }
                });             
                if (mSeekBar.getProgress()>0) {
                    runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        strober.start();
                    }
                    });
                }
                else {
                    runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        strober.interrupt();
                        relLayout.setBackgroundColor(color.all_white);
                    }
                    });
                }
          }
          public void onStartTrackingTouch(SeekBar seekBar) {}
          public void onStopTrackingTouch(SeekBar seekBar) {}          
        }); 

Here is the strobeLight() method:

public void strobeLight(){
    boolean lightIsOn=true;

    runOnUiThread(new Runnable() {
    @Override
    public void run() { 
            do {
                    if (lightIsOn){
                        relLayout.setBackgroundColor(color.all_black);
                        try { Thread.sleep(1000/(mSeekBar.getProgress()+2)); }
                            catch (InterruptedException e) {}
                        lightIsOn=false; 
                        strobeActivated=true;}
                    else{
                        relLayout.setBackgroundColor(color.all_white);  
                        try { Thread.sleep(1000/(mSeekBar.getProgress()+2)); }
                            catch (InterruptedException e) {}                       
                        lightIsOn=true; }
                    if (mSeekBar.getProgress()<1)
                        strobeActivated=false;
            } while (strobeActivated);
            relLayout.setBackgroundColor(color.all_white);
    }
});   
}   

Here is the LogCat for the code above:

11-28 17:17:58.383: E/ActivityManager(16877): ANR in com.marshall.meadows182 (com.marshall.meadows182/.LightNoTorch),  time=603431510
11-28 17:17:58.383: E/ActivityManager(16877): Reason: keyDispatchingTimedOut
11-28 17:17:58.383: E/ActivityManager(16877): Load: 1.53 / 1.62 / 1.62
11-28 17:17:58.383: E/ActivityManager(16877): CPU usage from 14662ms to 0ms ago:
11-28 17:17:58.383: E/ActivityManager(16877):   0.8% 16877/system_server: 0.4% user + 0.4% kernel / faults: 7 minor
11-28 17:17:58.383: E/ActivityManager(16877):   0% 14673/com.qikffc.android: 0% user + 0% kernel / faults: 151 minor
11-28 17:17:58.383: E/ActivityManager(16877):   0.2% 16957/com.android.systemui: 0.2% user + 0% kernel / faults: 1 minor
11-28 17:17:58.383: E/ActivityManager(16877):   0.1% 16999/com.android.phone: 0% user + 0% kernel
11-28 17:17:58.383: E/ActivityManager(16877):   0.1% 13/kondemand/0: 0% user + 0.1% kernel
11-28 17:17:58.383: E/ActivityManager(16877):   0% 68/rild: 0% user + 0% kernel / faults: 6 minor
11-28 17:17:58.383: E/ActivityManager(16877):   0% 14830/logcat: 0% user + 0% kernel
11-28 17:17:58.383: E/ActivityManager(16877):   0.1% 14868/com.marshall.meadows182: 0% user + 0% kernel / faults: 9 minor
11-28 17:17:58.383: E/ActivityManager(16877):   0% 24825/adbd: 0% user + 0% kernel
11-28 17:17:58.383: E/ActivityManager(16877):   0% 5446/com.google.android.apps.maps:NetworkLocationService: 0% user + 0% kernel
11-28 17:17:58.383: E/ActivityManager(16877):   0% 7839/wpa_supplicant: 0% user + 0% kernel / faults: 3 minor
11-28 17:17:58.383: E/ActivityManager(16877):   0% 17054/com.google.process.gapps: 0% user + 0% kernel / faults: 4 minor
11-28 17:17:58.383: E/ActivityManager(16877):   0% 25055/iqd: 0% user + 0% kernel
11-28 17:17:58.383: E/ActivityManager(16877): 2.7% TOTAL: 1.8% user + 0.8% kernel
11-28 17:17:58.383: E/ActivityManager(16877): CPU usage from 416ms to 935ms later with 99% awake:
11-28 17:17:58.383: E/ActivityManager(16877):   7.4% 16877/system_server: 0% user + 7.4% kernel / faults: 6 minor
11-28 17:17:58.383: E/ActivityManager(16877):     9.2% 16923/InputDispatcher: 1.8% user + 7.4% kernel
11-28 17:17:58.383: E/ActivityManager(16877): 3.8% TOTAL: 0% user + 3.8% kernel

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

§普罗旺斯的薰衣草 2024-12-25 08:49:41

该错误消息是不言自明的。不允许您在创建视图的线程(称为 UI 线程)之外调用视图的许多方法。

问题是

relLayout.setBackgroundColor(...);

在线程中运行的行。您应该像这样在 UI 线程上运行它们:

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        relLayout.setBackgroundColor(...);
    }
});

The error message is self-explanatory. You are not allowed to call many methods of views outside of the Thread they were created on, known as the UI Thread.

The problem is the lines

relLayout.setBackgroundColor(...);

which are run in your thread. You should run them on the UI thread like this:

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        relLayout.setBackgroundColor(...);
    }
});
2024-12-25 08:49:41

这是正常的,您无法更改那里的 UI。我建议使用 AsyncTask 并更改 onPostExecute 方法上的 UI。无论如何,如果您不想更改,则必须使用处理程序更改 ui。

That's normal, you can't change the UI there. I would suggest to use an AsyncTask and change the UI on onPostExecute method. Anyway if you don't want to change then you must change the ui using handlers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文