Wednesday 25 December 2019

multithreading - Android While-Loop using Thread



im trying to make a thread that will run a While-loop and inside the while-loop actions that will change the UI should take place :



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();
}


However my first problem is that the following error occurs :




 Only the original thread that created a view hierarchy can touch its views.


and the second problem is that i have heard that using threads in background will consume toooooo much of the device CPU, fact that may lead to my app-crash. Does something like that indeed happens ?
thank you for your answers


Answer



First off, I recommend reading this article, as the current construction you're using is kind of .. dirty ..



Anyway, in order to respond to the actual error you're receiving, it's obvious that you can't update the UI thread from a background thread.
Why ? Because if you could, imagine 10 different threads updating the UI at the same time .. That'd give buggy-looking applications, wouldn't it?

Also it would mean that every UI element would need to be locked, synchronised, in order to provide more or less consistent behaviour. This would defeat the purpose of having threads perform 'hard work', they'd become dependant on the UI ..



(If anyone can give a very clear reason / reference to a guideline and / or reason comment it and I'll adjust the answer)



So, in Android you can get a hold of the main Looper, a utility used to perform tasks in a sequential order, performed on a specified thread.
What we hereby do, is actually queueing our operations to be performed on the main thread.



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();
}
}



Disclaimer, this code is untested and from the top of my head. If it does not do what you think it should do, feel free to mention it.



The structure is adapted, what you have to do now is start the thread as you were attempting to, or use an Executor.



Thread myThread = new Thread(new GameHandler());
myThread.start();


In case I'm not clear enough on the subject, these links are for reference :





No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print &q...