线程无法访问视图 - Android
我正在编写一个手电筒应用程序,它是任何没有手电筒的手机的“屏幕灯”。我想要一个启用频闪灯功能的设置。然而,对于这种类型的“手电筒”,我认为最简单的方法是更改视图的背景。我在单独的线程中执行此操作,因为我使用 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
该错误消息是不言自明的。不允许您在创建视图的线程(称为 UI 线程)之外调用视图的许多方法。
问题是
在线程中运行的行。您应该像这样在 UI 线程上运行它们:
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
which are run in your thread. You should run them on the UI thread like this:
这是正常的,您无法更改那里的 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.