We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hi
Working in Android Studio with Processing for Android, I'm trying help the start of my app by having the loading of images transferred to a parallel thread
It seem an AsyncTask class is the way to go and I found a good reference to see how it is done The thing is, instead of 'Bitmap' and 'ImageView' I'm here working with PImage
Any idea on how to turn this Class
class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private int data = 0;
public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
// Decode image in background.
@ Override
protected Bitmap doInBackground(Integer... params) {
data = params[0];
return decodeSampledBitmapFromResource(getResources(), data, 100, 100));
}
// Once complete, see if ImageView is still around and set bitmap.
@ Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
and this code
public void loadBitmap(int resId, ImageView imageView) {
BitmapWorkerTask task = new BitmapWorkerTask(imageView);
task.execute(resId);
}
into something that would work for PImage ?
Answers
PImaget.getNative() returns a bitmap object. Would that help?
Check also the setNative() in the above reference. Lastly, I was working with ImageView objects in this recent discussion. Hopefully this helps:
https://forum.processing.org/two/discussion/comment/118853/#Comment_118853
Kf
thanks for the answer @kfrajer
My point here, is to offload the many loadImage("myImage.png") work to another thread.
I am playing around with a backgroundWorker function like so
but with no success because, even though I send my PImage variable inside the pramas like so
params[0].pImage is always null
ok , I got it to work so here is how it goes:
inside my main I added 2 Classes
One to create the params to feed my AsyncTask
One is my AsyncTask
First one goes:
Then the AsyncTask goes:
then I have to use some Arrays, One with the file names (discretImgString[]) and one with the PImage variable names (discretIMG[]) (which won't be used but help my keep track of my ressources)
Here is how I call the image loading from my setup()
So, using this trick I can start my sketch with a neat little loading screen and display a loading percentage animation using this ressourceCounter int
Out of interest, what's missing with
requestImage()
?** insert facepalm gif here **
oh my ! it took me 2 days to work out this AsyncTask thing and now you come and tell me that :S It's like painfully forcing a lock and having someone showing you the door is actually open
Well, at least I learned a lot of AsyncTask thing in the process and I guess it'll be useful for things beyond images, like sounds, json stuff etc they say alway look at the bright side right ?
There's also thread(): https://Processing.org/reference/thread_.html
You should 1st look Processing's API reference to check whether the functionality you need is already there. ;)
wow, another cool function !
and how nice it is to have everyone come to give me the answer to my question one week after I asked, and tell me all the work I have put into solving my problem alone was just a waste of time
do you suggest learning the reference by heart and ditch the forum altogether ?
anyway, if anyone of you is interested in criticizing my work, you can find it here now : https://play.google.com/store/apps/details?id=gg.rich.me.fuzo
:D
@phoebus ha ha, don't worry - we've all done it - generally at least once a week! :-)
@GoToLoop - generally agree with you about the reference, but
thread()
is quite limited compared to what the original code is doing. Not to mention, don't get me started on how broken that thread() example actually is! ;-)Almost all of Processing's API is a simplification of how things are done on bare metal Java. ~O)
It's not a question of how limited the API is, but whether it's enough for what we wanna lazily accomplish. :\">
Many Processing's reference examples can be broken, incomplete or even wrong. :-O
I just post links to them b/c I'm lazy. (:|
@GoToLoop - yes, and it isn't (easily) in this case!
btw - the example is broken because it doesn't use synchronized or volatile to set the shared variable, which means the JVM may (or at least is free to) make
time = json.getString("time");
a no-op. There's also no checking for whether a load is already in progress, which would be ideally handled inthread()
, so has the potential to crash.I'm all for simplifying things over bare metal Java - that's kind of my key interest - but not encouraging completely broken practise in the process. There are much better ways to simplify this!
""
.try/catch ()
block for it.null
. Fix, use defaultValue:time = json.getString("time", "");
https://Processing.org/reference/JSONObject_getString_.html
In my experience w/ threads in Java, I've never had a thread-shared field failing to get updated and seen by all other threads b/c it wasn't declared as
volatile
or wasn't inside asynchronized
block or method. :-\"When dealing w/ shared fields, each Java Thread caches them for performance reasons. \m/
And when a thread reassigns a shared field, of course there's some latency for the other threads to actually "see" that change. :-SS
But eventually, all threads end up seeing the new assigned value.
And it doesn't take that much. It's almost instantly! :-bd
What
volatile
does to a field is to guarantee that all threads sharing that field sees any change to its stored value immediately.But in that particular example, we've got 2 threads sharing variable time:
The "Animation Thread" and the 1s created by thread().
I'm taking into consideration that each thread() dies before a new 1 is created at about half second rate. :ar!
So each thread() reassigns the shared variable time w/ another String object reference value.
And the main "Animation Thread" simply displays the current String assigned to time when text() is invoked at about 60 FPS.
I dunno how much latency the "Animation Thread" takes to "see" the latest current String assigned to time.
Does it take 1, 2, 3, 4, or 5 milliseconds for the "Animation Thread" to realize the new reference value stored in variable time by the other thread()? I dunno! 3:-O
What I know is that the update is so fast that for me it is instantly!
Whether time is
volatile
or not doesn't make an iota diff. for this particular example! =P~Ru sure Java would be so irresponsible to no-op an assignment operation, so the other threads would never eventually see the changed value in a shared non-
volatile
field??? @-)So if I change the index 0 of some ArrayList in a thread, another thread would never see that change??? :-SS
Sorry @neilcsmith_net; that doesn't make any sense to me. :-/
Actually, that would break many Java programs, including Processing sketches which doesn't care about
volatile
norsynchronized
blocks if what you've stated above could be true! =;What I don't like about that thread() example is that it keeps creating a new Thread over & over for something that is supposed to keep ongoing during the whole time the sketch is running. 8-X
How about invoking thread() once in setup(), and have its code inside an infinite loop w/ delay(): *-:)
https://Processing.org/reference/thread_.html
I love how I couldn't get 2 lines of tips to get unstuck yesterday, and now that I have my thing working, you come and write books about the damn topic bite me
@GoToLoop
Yes! And no it's not irresponsible, it's how optimization works. ;-)
As one of many (many) links on this - have a read of https://stackoverflow.com/questions/9580605/is-it-possible-to-modify-a-non-volatile-variable-such-that-another-thread-is-abl
This might work fine for you, always, never, or just for a while. It might work fine on one Java version but not the next, one OS but not the next, one CPU but not the next. Or work until HotSpot kicks in with some extra optimizations. You might be surprised how different the code emitted by HotSpot is from what you write.
Incidentally, the thread termination rules might actually make the multiple threads option more stable, but only because of other things going on around the animation thread.
Not sure this has much to do with solving @phoebus original problem! :-)
@phoebus -- unfortunately it was two kinds of busy - busy at work, and lots of threads pouring in eg for GSOC2018, so some things blew by.
That said, this might be a case where framing what you want in title and top line in terms of your goal would get better attention. I saw this question as: how do you use AsyncTask. :-?? But it was actually: how can I use threads for x.
boolean
datatype occupies. @-)boolean
would occupy more than 1 byte of memory. That'd be stupid for many reasons! :@)@GoToLoop - you can believe what you want! ;-)
All specifications are vaguer than their implementation! But the Java Memory Model spec is quite specific. I read Peter's response and not sure what to make of it - "don't believe" and "might never" are not two statements that go well together IMO.
btw - don't forget
draw()
might get optimized - it's the read on that side that's more problematic.Perhaps, but you use one all the time! I think you'll findboolean
,byte
,char
andshort
all occupy 4 bytes. ;-)https://docs.oracle.com/javase/specs/jvms/se7/jvms7.pdf
EDIT: OK, engage brain, spot the "deliberate" mistake. That's the JVM spec, what I was actually thinking of was around alignment, which is more a case of it depends.