线程无法访问视图 - Android

时间:2011-11-28 21:25:27

标签: android multithreading layout view

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

以下是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

2 个答案:

答案 0 :(得分:2)

错误消息不言自明。不允许在创建它们的线程之外调用许多视图方法,称为UI线程。

问题是线

relLayout.setBackgroundColor(...);

在你的线程中运行。您应该在UI线程上运行它们,如下所示:

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

答案 1 :(得分:0)

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