0

I am new in Android.I have a global variable in Main class:

public class MainActivity extends AppCompatActivity {
private int lenghtOfFile;

I'v created a AsyncTask to connect Internet and get file size from download link:

   private class GetSizeOfFile extends AsyncTask<String, Void,Integer> {

    @Override
    protected  Integer doInBackground(String... stringURls) {
        String stringURl = stringURls[0];
        Log.i("===", "doInBackground: " + stringURl);

        try {
            URL url = new URL(stringUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            lenghtOfFile = connection.getContentLength();


        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return lenghtOfFile;
    }

    @Override
    protected void onPostExecute(Integer lenghtOfFile) {
        super.onPostExecute(lenghtOfFile);

            Log.i("====", "size of file in Thread: " + lenghtOfFile);

    }
}

when I logged in thread my global variable had been initialized:

Log.i("====", "size of file in Thread: " + lenghtOfFile);

but im my method that i have executed this thread my global variable had not been initialized ant its value is 0?

        new GetSizeOfFile().execute(stringUrl);

    Log.i("====", "size of file after Thread: " + lenghtOfFile);`

my logcat:

02-22 13:20:26.516 8167-8167/com.example.manifest.simplefiledownloadmanager I/===: addURLToList: http://cdn.p30download.com/?b=p30dl-software&f=VLC.Media.Player.v2.2.4.x64_p30download.com.rar
02-22 13:20:26.516 8167-8167/com.example.manifest.simplefiledownloadmanager I/====: file name : ?b=p30dl-software&f=VLC.Media.Player.v2.2.4.x64_p30download.com.rar
02-22 13:20:26.516 8167-8167/com.example.manifest.simplefiledownloadmanager I/====: size of file after Thread: 0
02-22 13:20:26.516 8167-8306/com.example.manifest.simplefiledownloadmanager I/===: doInBackground: http://cdn.p30download.com/?b=p30dl-software&f=VLC.Media.Player.v2.2.4.x64_p30download.com.rar
02-22 13:20:32.836 8167-8167/com.example.manifest.simplefiledownloadmanager I/====: size of file in Thread: 33344550

after few second lenghtOfFile in thread is initialized. how can i do some work that in this line I get right size of file from thread? Log.i("====", "size of file after Thread: " + lenghtOfFile);

sayres kabir
  • 362
  • 4
  • 22

2 Answers2

0

This is caused by the fact that the Log command in the main thread happens BEFORE the one in the AsyncTask.

The task is sent to run in the baqckground and the main one continues on its merry way.

This can be clearly seen in the logcat by the times of the log lines themselves.

02-22 13:20:26.516 8167-8167/com.example.manifest.simplefiledownloadmanager I/====: size of file after Thread: 0

02-22 13:20:32.836 8167-8167/com.example.manifest.simplefiledownloadmanager I/====: size of file in Thread: 33344550

Notice how the one from the thread happens later.

theblitz
  • 6,683
  • 16
  • 60
  • 114
  • I want send this lenghtOfFile variable to another place. every time 0 is send. how can I do fix it?I want send new value instead 0 – sayres kabir Feb 22 '17 at 13:48
  • You can only use it after the value is changed. That would be inside onPostExecute. Since that runs in the UI thread you can do anything you want there. – theblitz Feb 22 '17 at 15:33
0

You have to wait for lenghtOfFile to be updated. This can take an arbitrary amount of time, possibly not happen at all (if there's an error). So the best way is not to wait for it to be updated but instead to be notified after it was updated. A sensible solution would be the usage of the Observer Pattern (tutorial featuring PropertyChangeEvent, tutorial with RxJava). Another possibility is the usage of an event bus like EventBus. If you have just one component that needs to be informed you can call it directly from onPostExecute(Integer lenghtOfFile).

If you really want to wait for lengthOfFile to be updated, use something like a CountDownLatch:

public class MainActivity extends AppCompatActivity {
    private final lengthOfFileLatch = new CountDownLatch(1);
    private int lenghtOfFile;
}

and:

@Override
protected void onPostExecute(Integer lenghtOfFile) {
    MainActivity.this.lengthOfFile = lengthOfFile;
    lengthOfFileLatch.countDown();
}

and:

new GetSizeOfFile().execute(stringUrl);
lengthOfFileLatch.await(5, TimeUnit.SECONDS);
Log.i("====", "size of file after Thread: " + lenghtOfFile);`

If the latch isn't triggered within 5 seconds you'll still get zero. Otherwise you would block forever (which is possible too without any arguments).

aha
  • 3,702
  • 3
  • 38
  • 47