我试图创建一个将运行While循环的线程,并在while-loop中执行将会更改UI的操作:
public void GameHandler()
{
layout = (RelativeLayout) findViewById(R.id.MyLayout);
params=new RelativeLayout.LayoutParams(30,40);
btn1 = (Button) findViewById(R.id.MovingObj);
xBounds=new int[2];
yBounds=new int[2];
xBounds[0]=0;
xBounds[1]=layout.getWidth();
yBounds[0]=0; //will change once i set up the screen settings !
yBounds[1]=layout.getHeight();
selectFlyingObject();
Runnable myRunnable = new Runnable() {
@Override
public void run() {
while (CurrentXLocation <= xBounds[1] + 10) {
CurrentXLocation = CurrentXLocation + 1;
params.leftMargin = CurrentXLocation;
params.topMargin = 50;
btn1.setLayoutParams(params);
SystemClock.sleep(1000 - SpeedRate);
}
}
};
Thread myThread = new Thread(myRunnable);
myThread.start();
}
但是我的第一个问题是发生以下错误:
Only the original thread that created a view hierarchy can touch its views.
并且第二个问题是我听说在后台使用线程将消耗太多的设备CPU,这可能导致我的应用程序崩溃。这样的事情确实发生了吗? 谢谢你的回答
答案 0 :(得分:2)
首先,我建议您阅读this article,因为您正在使用的当前构造有点......脏......
无论如何,为了回应您正在接收的实际错误,很明显您无法从后台线程更新UI线程。 为什么?因为如果可以的话,想象一下10个不同的线程同时更新UI。那会给出看起来很漂亮的应用程序,不是吗? 此外,它还意味着需要锁定,同步每个UI元素,以便提供或多或少的一致行为。这将使线程执行“艰苦工作”的目的失败,他们将依赖于UI。
(如果有人能够给出明确的理由/参考指南和/或理由发表评论,我会调整答案)
因此,在Android中,您可以获得主Looper,一个用于按顺序执行任务的实用程序,在指定的线程上执行。 我们在此做的,实际上是将我们的操作排队在主线程上执行。
public class GameHandler implements Runnable {
Handler mHandler = new Handler(Looper.getMainLooper());
Layout mLayout;
View mView;
int currentX, mSpeedRate;
public GameHandler(Layout layout, View viewToAnimate, int speedRate) {
mLayout = layout;
mView = viewToAnimate;
mSpeedRate = speedRate;
}
public void handleGame() {
final RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(30, 40);
int[] xBounds = new int[2];
int[] yBounds = new int[2];
xBounds[0] = 0;
xBounds[1] = mView.getWidth();
yBounds[0] = 0; //will change once i set up the screen settings !
yBounds[1] = mView.getHeight();
selectFlyingObject();
while ( currentX <= xBounds[1] + 10 ) {
currentX = currentX + 1;
params.leftMargin = currentX;
params.topMargin = 50;
mHandler.post(new Runnable() {
@Override
public void run() {
mView.setLayoutParams(params);
}
});
SystemClock.sleep(1000 - mSpeedRate);
}
}
void selectFlyingObject() {
// No idea what you're doing here, but keep in mind you're still working on the
// background thread if you call this method from somewhere not wrapped in the mHandler
}
@Override
public void run() {
handleGame();
}
}
免责声明,此代码未经测试且从我的头脑中开始。如果它没有做你认为它应该做的事情,请随意提及。
结构已经过调整,您现在要做的就是在尝试时启动线程,或者使用Executor
。
Thread myThread = new Thread(new GameHandler());
myThread.start();
如果我对该主题不够清楚,这些链接仅供参考:
答案 1 :(得分:0)
&#34;我听说过......&#34;不是一个特别可靠的信息来源。使用后台线程在Android中绝对没问题。每秒产生不朽的线程会导致应用程序崩溃,就像制作一个无限循环一样 - 并且使用来自其他开发者的相同评论。
你的问题&#34;是不言自明的 - 因为UI工具箱中的每个Java并发教程都指出 - 不要从背景线更新UI 。使用众多机制之一向UI线程发送信号来执行此操作。在你的情况下 - Timer
很适合(它会每隔x秒唤醒并执行一次运行)。