0

I have a if-statement in the start of my app

    if (ready.equals("yes")){
...
}

and later on my code I have

ready="yes";

but the if statement is never called, why? The ready="yes"; is called from a background thread, is that why?

    public void DownloadFromUrl(final String fileName) {  //this is the downloader method
            new Thread(new Runnable() {
                public void run() {
        try {

            URL url = new URL("https://xxxxxxx");
            File file = new File(PATH + fileName);

            long startTime = System.currentTimeMillis();
            Log.d("ImageManager", "download begining");
            Log.d("ImageManager", "download url:" + url);
            Log.d("ImageManager", "downloaded file name:" + fileName);
                    /* Open a connection to that URL. */
            URLConnection ucon = url.openConnection();

                    /*
                     * Define InputStreams to read from the URLConnection.
                     */
            InputStream is = ucon.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is);

                    /*
                     * Read bytes to the Buffer until there is nothing more to read(-1).
                     */
            ByteArrayBuffer baf = new ByteArrayBuffer(50);
            int current = 0;
            while ((current = bis.read()) != -1) {
                baf.append((byte) current);
            }

                    /* Convert the Bytes read to a String. */
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(baf.toByteArray());
            fos.close();
            Log.e("Ready or not", ready);
            ready="yes";
            Log.d("ImageManager", "download ready in"
                    + ((System.currentTimeMillis() - startTime) / 1000)
                    + " sec");
            Log.e("Ready or not", ready);



        } catch (IOException e) {
            Log.d("ImageManager", "Error: " + e);
        }

    }
    }).start();
Emilio Gaines
  • 95
  • 1
  • 10

2 Answers2

1

Correct me if I'm wrong. If you're saying that your code looks like this:

new Thread(new Runnable() { public void run()
                            {
                                // thread code
                                if (ready.equals("yes")) {
                                    // handler code
                                }
                                // more thread code
                            }).start();

// later on...
ready = "yes";

And you're asking why ready = "yes" doesn't execute before if (ready.equals("yes")), then that's because multiple threads aren't guaranteed to execute in a certain order. If you want to wait until ready.equals("yes") before you execute the if statement, then you have to use the Object.wait() and Object.notifyAll() methods:

// this is a field
private Object waitOnThis = new Object();

new Thread(new Runnable() { public void run()
                            {
                                // thread code
                                waitOnThis.wait(); // blocks until notify / notifyAll is called on waitOnThis
                                // by this point ready.equals("yes")
                                if (ready.equals("yes")) {
                                    // handler code
                                }
                                // more thread code
                            }).start();

// later on...
ready = "yes";
waitOnThis.notifyAll(); // unblocks threads waiting on waitOnThis

Good luck!

EDIT: Be sure to wrap each of the code fragments above in a synchronized (waitOnThis) block, or else you'll get an IllegalMonitorStateException.

James Ko
  • 32,215
  • 30
  • 128
  • 239
  • yeah but the ready="yes" will ALWAYS be called after the if-statement since it runs in the background, seperate from the main activity and is called about 2-3 seconds AFTER the if-part is checked – Emilio Gaines Jun 22 '15 at 03:24
  • 2
    May I suggest that anytime you use `equals` with a constant, put the constant on the left: `"yes".equals(ready)`. This way you always avoid `NullPointerException`s. – Jared Burrows Jun 22 '15 at 03:42
  • acually the (ready.equals("yes")) was in onCreate/a void but I tried it your way but I get unhandled.exception on waitOnThis.wait(); – Emilio Gaines Jun 22 '15 at 03:44
  • @EmilioGaines Whoops, it looks like you need to be in a [synchronized](http://stackoverflow.com/a/1537133/4077294) block for `Object.wait()` to work. Try wrapping everything in a `synchronized (waitOnThis)` block (and if that happens in `DownloadFromUrl`, add `synchronized` there as well). – James Ko Jun 22 '15 at 03:48
0

Application's OnCreate will only be called once at the beginning when the app is created.

Consider using callback if you want to notify that the download has finished.

Malvin
  • 692
  • 5
  • 8