I am making an android game which is made up of a game loop that is constantly running as well as use of the android UI stuff. So they need to be in separate threads to work concurrently.
I am planning to put the game loop inside an AsyncTask however it says in the developer.android documentation that
AsyncTasks should ideally be used for short operations (a few seconds at the most.)
My game loop will in theory be operating indefinitely and almost always for more than a few seconds. Is the asynctask the right place to put this then or is there another preferred method to split up a game loop and the UI operations
AsyncTasks are for short operations only, as the documentation has stated. Also, they usually do some work that shouldn't interfere with the UI. Hence, "Async" and "Task".
What you should use instead is a new Thread. This is called Multi-Threading. There are a lot of Game Frameworks out there which will have problems with android's UI. Though you have not stated what UI Operations you are talking about, but if you plan to use the android's widgets(UI), you could call Activity.runOnUiThread() to run a code on the UI Thread, for example, changing a TextView's text.
Here is a snippet on how you would create a never ending loop in a new thread(or something like this, i dont remember if the function is private):
new Thread(new Runnable() {
#Override
private void run() {
while(true) {
//your code goes here
}
}
});
Although AsyncTask allows you to perform background operations and publish results on the UI thread without having to manipulate threads, it should ideally be used for short operations (a few seconds at the most).
To keep things simple, you could use a Handler, or even better, research about the various APIs provided by the java.util.concurrent package.
import android.os.Handler;
// Create the Handler
private Handler handler = new Handler();
// Define the code block to be executed
private Runnable runnable = new Runnable() {
#Override
public void run() {
// Insert simulation processing code here
// Repeat 60 times per second
handler.postDelayed(this, 1000 / 60);
}
};
// Start the Runnable immediately
handler.post(runnable);
Remember that multi-threading is the easy part. Correct synchronization is hard.
Related
I am using priority job queue , there are number of jobs running in parallel, so that their result populates on UI at same time which takes application to ANR, is there any way , so that i can run asynchronous calls and populate ui synchronously?
UI is always populated synchronously, if it is done in correct way. The correct way is to call activity.runOnUiThread(Runnable), directly or indirectly. Seems that your problem is that your jobs post to UI thread in a too high rate.
First, check if the Runnables to update UI does only UI work. Any calculations should be done outside the UI thread. If it is so, create an intermediate object which makes pauses between UI updates from the parallel jobs and so lets the UI thread to respond to updates from user. It can look as follows:
public class PauseMaker {
Semaphore sem = new Semaphore(1);
public void runOnUiThread(Runnable r) {
sem.aquire();
Thread.sleep(1);
activity.runOnUiThread(new Runnable(){
try {
r();
} finally {
sem.release();
}
});
}
}
You can use the zip operator of rxjava2 to merge the responses together and when the combined response comes you can populate the UI synchronously .. for reference you can check..
http://www.codexpedia.com/android/rxjava-2-zip-operator-example-in-android/
Note The zipper will the return merged response after all the responses are received
I have a small Android application in which I need to do some FTP stuff every couple of seconds.
After learning the hard way that running network stuff on the UI thread is something Android does not really like, I've come to this solution:
// This class gets declared inside my Activity
private class CheckFtpTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... dummy) {
Thread.currentThread().setName("CheckFtpTask");
// Here I'll do the FTP stuff
ftpStuff();
return null;
}
}
// Member variables inside my activity
private Handler checkFtpHandler;
private Runnable checkFtpRunnable;
// I set up the task later in some of my Activitiy's method:
checkFtpHandler = new Handler();
checkFtpRunnable = new Runnable() {
#Override
public void run() {
new CheckFtpTask().execute((Void[])null);
checkFtpHandler.postDelayed(checkFtpRunnable, 5000);
}
};
checkFtpRunnable.run();
Is this good practice to perform a recurring task that cannot run on the UI thread directly?
Furthermore, instead of creating a new AsyncTask object all the time by calling
new CheckFtpTask().execute((Void[])null);
would it be an option to create the CheckFtpTask object once and then reuse it?
Or will that give me side effects?
Thanks in advance,
Jens.
would it be an option to create the CheckFtpTask object once and then reuse it? Or will that give me side effects?
No, there will be side-effects. Quoting the docs Threading Rules:
The task can be executed only once (an exception will be thrown if a second execution is attempted.)
You will just need to create a separate instance of the task each time you want to run it.
And I'm not sure why you need the Runnable or Handler. AsyncTask has methods that run on the UI Thread (all but doInBackground(), actually) if you need to update the UI.
Check this answer if you need a callback to update the UI when the task has finished.
You should create a new Async task for every call.
See the Android Documentation: AsyncTask. According to this documentation:
The task can be executed only once (an exception will be thrown if a second execution is attempted.)
Specifically check out the threading rules section. There is a similar answer here, https://stackoverflow.com/a/18547396/2728623
Java ThreadPools and the ExecutorFramework allows you to execute threads as needed and reduces thread creation overhead. Check out the singleThreadExecutor. The thread pool usage is pretty easy too!
I have one library which is linked to my Android application, I am calling some functions of that lib from my android Activity and those function calls are time taking (4-5 seconds).
I can not call this functions in separate thread (using AsyncTaks, Threads) because of the library limitations.
When i call these function and when these function are in process at the same time my UI does not respond to user activities and to avoid that i am displaying processing screen and if in-between user performs any key actions then i get ANR error.
How can i avoid this ANR or there is no way i can avoid it other that putting time taking process in separate thread?
Thanks.
better read this article and watch google IO videos (like this one and this one) .
if you don't have time for this , simply remember this simple rule:
long operations (like internet operations , DB operations , IO operations , and anything that could simply take longer than 5 seconds ) could cause ANR if they occur on the UI thread.
for updating the UI , you must use the UI thread . if you need to do it after/during the long operation , use classes such as : Handler , AsyncTask , View.post , Activity.runOnUiThread .
Who wrote the library and what is it? The only reason I can think of as to why it would throw an exception is that it is trying to update the UI from the thread that you call it on. If the library methods take 4-5 seconds to compete then they should provide you with a callback mechanism that you can update your UI on the UI thread.
new Thread("Slow native process") {
public void run() {
// call your "time taking process", passing in the callback (you could implement in the outer class and pass "this"...)
callNativeMethod( args, new YourCallbackInterface() {
public void onResult( String response ) {
activity.runOnUiThread( new Runnable() {
// update UI
});
}
});
}
}.start();
1.
I have main UI thread and it uses library functions.
MainUI {
library.funcA(1);
library.funcB(2,3);
}
I don't want Main-Thread to wait for the end of each call. Also creating new thread for each call is ineffective and not thread-safe so I want them to run on another same thread.
So I created another thread with a single message queue / handler.
MainUI {
handler.post(new Message(FUNC_A,[1]));
handler.post(new Message(FUNC_B,[2,3]));
}
but it seems having overhead that I need to create new Message object every time and decode it again in handleMessage(). Furthermore It looks ugly to handle the various number of arguments packing/unpacking. I thought making all functions as Runnable and post them to handler, but functions have different arguments and I need to make new classes extending Runnable class!
my current plan is to insert synchronized keywords into every function in library so threads run one by one,
but I dislike many threads creating/disappering so making system heavy (also not thread-safe). I want to hear opinions.
2.
if the library is called from many threads (not only Main-thread), what's the best way to convert calls to run on the library's own single thread?
In my opinion, your current approach is feasible option to make thread-safe. However, if you want to go for having Runnable passed to handler, you could consider overloading your Runnable class. Here is pseudo-code
private Class MyRunner extends Runnable{
public MyRunner(){
//This is without any argument
}
public MyRunner(arg1){
//This is with 1 argument
}
public MyRunner(arg1,arg2){
//This is with 2 arguments
}
}
Still, you will have many instances of MyRunner class created.
You can use a Runnable like this:
int x = 1;
int y = 2;
// "a" and "b" are here to show how variable values can be sent to funcB.
// You could skip this and just have "funcB( 1, 2 )", of course.
final int a = x;
final int b = y;
handler.post( new Runnable() {
public void run() { library.funcB( a, b ); }
} );
The handler bit is a bit trickier. It has to run a looping thread to run each Runnable from the queue. Then it has to have a post method to put things on the queue. Some form of blocking queue would be the simplest way to link the two, saving you from having to do your own Object.wait/Object.notify. Synchronizing the post method would be the easiest way to keep multiple threads from tripping over each other.
Currently I'm using the following construction:
while(continue)
{
if(somethingChanged)
{
draw();
}
}
Is this way of waiting efficient, or is there a better way to do this?
--
As requested, more info:
I'm drawing on a SurfaceView, with a Thread locking the Canvas and calling the onDraw(Canvas) method. When the thing I have drawn hasn't changed, I don't need to call the onDraw(Canvas) method, so I keep a boolean somethingChanged.
Also, when I touch the screen, I draw let's say a circle at the point of touch, so when I'm touching the screen, somethingChanged is true.
You can also use a wait() and make the other threads notify() this one when something has changed (if the somethingChanged is changed by other threads).
You probably doing a game, I recommend that article: http://dewitters.koonsolo.com/gameloop.html There are very good possible solutions for your request.
Android has a better mechanism regarding idle loops than the std java approach.
It consists of a Looper and a Handler which do the work for you:
Handler myHandler;
...
public void run() {
Looper.prepare(); //this tells Android that your thread will contain a loop
myHandler = new Handler() {
public void handleMessage(Message msg) {
draw();
}
};
Looper.loop; //starts the loop
}
All you have to do to call the draw method is to send a message to that handler instead of setting the boolean var.
Message mess;
myHandler.sendMessage(mess)
That way you can also send any object in that message to the loop, too and android does the thread synchro and message queue stuff for you. And - most importantly - it is efficient, too.
If nothing changed, this is an endless loop that will very probably use 100% cpu, so I'd say that you should at least add some Thread.sleep() calls to give other threads a chance do to something (e.g. changing the value of somethingChanged)
Usually, in infinite loops, you should have some mechanism to avoid it to take over all time of the cpu. This is done, for example, with a sleep. Even a brief sleep will alleviate the use of the processor.
Assuming that this code is in an thread:
while(continue)
{
if(somethingChanged)
{
draw();
}
Thread.sleep( mySleepTime );
}