2

Well in app I'm trying to pull the data from sever for every 4 sec,and update the app. I'm using handler,in that I'm calling AsynTask to fetch the data from server for every 4 sec.

Just I'm worried about the instance created for AsynTask every 4'sec causes any problem ?

This is what I'm doing.

private static final int DELAY = 1000 * 4;
final Handler printHandler = new Handler();
private boolean keepLooping = true;
printHandler.postDelayed(printStuff, DELAY);


Runnable printStuff = new Runnable(){
     @Override
     public void run(){
        // call AsynTask to perform network operation on separate thread
         new DownloadMainScore().execute("http://server/root/score.php");
         if(keepLooping)
             printHandler.postDelayed(this, DELAY);
     }
};
xaif
  • 553
  • 6
  • 27
Uday
  • 1,619
  • 3
  • 23
  • 48
  • Are you sure your data shall be already updated to view in your app before another call to data? – Saqib Apr 09 '14 at 06:54
  • I'm updating the UI in ```onPostExecute(String result)```. – Uday Apr 09 '14 at 06:55
  • you better use service for that, keep it running and after every 4 seconds check your data, put that result call to handler or whatever and update your view. – Saqib Apr 09 '14 at 06:57
  • As per your requirement, using Volley library would be a better approach. Add your request to RequestQueue every n time to get data from server. – Anuj Sharma Apr 09 '14 at 07:12
  • I will check into that library.ThankQ. – Uday Apr 09 '14 at 07:25

4 Answers4

3

On your choice of concurrency tool:

You are right that this is not so good. AsyncTasks are designed to be useful helpers when designing occasional asynchronous calls that then need to update a UI. As such, in old (< 1.6) versions of Android the maximum thread pool size was 10!

It would be better to go straight to the very robust Java out of which AsyncTask is built. Given you want to do this repeatedly, try a ScheduledExecutorService. I see they've even made a nice example for you.

Or, given that you seem to be getting a score down, best might be to maintain a persistent connection over a protocol like XMPP, for which there are many Java server and clients.

Finally, you might like to look at gcm.

On design issues in general

I see you want to print a score frequently. Once every four seconds in fact. But what's the point is the score hasn't changed? Furthermore, what if you've got a slow internet connection, and eight seconds later the one for four seconds ago hasn't finished? Right now you will set off yet another download request, even though the other one when it comes back will be up to date!

The solution is to decouple the download mechanism and the UI update mechanism. One way to do it is to have your scheduled download on a single threaded executor- not something you can control in an AsyncTask, which when finishes causes the UI to update and show the score.

Wishing you the best of luck!

Code sketch

Don't have environment set up right now, but in a very rough code sketch (check syntax), using a scheduled executor would look like: In class:

private final ScheduledExecutorService downloadScheduler = Executors.newSingleThreadScheduledExecutor(1);

Then elsewhere, wherever you start doing this

final Runnable scoreHttpRunnable = new Runnable() {
    @Override public void run() {
...
//do Http Syncronously here- I guess whatever is in the doInBackground(...) part of that Async task you wrote!
...
final int newScoreResult = ... (do whatever you do here)
...
runOnUiThread(new Runnable() { @Override public void run() { yourView.updateHoweverYouLike(newScoreResult); } })
...
};
downloadScheduler.scheduleAtFixedRate(scoreHttpRunnable, 0, 4, TimeUnit.SECONDS);

Going one of the other two routes is really too much to post in a single answer to a question. That'd be a another SO question if there isn't already one.

Tom
  • 1,773
  • 15
  • 23
  • Thanks Tom,I like your way of explanation. it would be great if you provide a snippet of example code to do it. – Uday Apr 09 '14 at 07:16
  • Updated for the Executors stuff. Hope that helps. The other two options really are two broad to give a sample to from scratch. Best. You sound very competent at http so I haven't repeated the downloading mechanism. – Tom Apr 09 '14 at 07:28
  • I have one doubt, ScheduledExecutorService is a low level api and some people says that using low level api is not good! – Uday Apr 09 '14 at 11:17
  • Hey Uday. Sometimes using a low level api is not good. But I'd dispute that java.util.concurrent is a low level api particularly! It is the default choice for non-android java apps, and for Android apps- well, we use it all the time. The mistake is people try to provide their own concurrency implementations using their own locks and conditions. That is indeed, bad news, and I suspect what people are referring to. Best. – Tom Apr 09 '14 at 11:29
2

Be sure that next call send to asyc class only after once its done for that make a variable(IsLoadRunning) and make it true in on preExecute() and false in onPOstExecute and add a condition if(!IsLoadRunning){new DownloadMainScore().execute();}

Ando Masahashi
  • 3,112
  • 2
  • 24
  • 41
Android Priya
  • 686
  • 1
  • 6
  • 23
1

As official documentation states

AsyncTasks should ideally be used for short operations (a few seconds at the most.)

Services can serve better in you case. Have a look at the accepted answer here

Community
  • 1
  • 1
Ahmad Dwaik 'Warlock'
  • 5,953
  • 5
  • 34
  • 56
  • Putting the concurrency in a service could be good too, Ahmad. If for whatever reason we can't have some kind of server push, how did you envisage doing the download repeatedly inside this service? – Tom Apr 09 '14 at 07:38
  • I tried IntentServices , But it is slow compared to AsynTask. – Uday Apr 09 '14 at 07:45
  • @Tom I guess you will have to use it along with alarm manager, or create your own scheduler. – Ahmad Dwaik 'Warlock' Apr 09 '14 at 09:04
  • Alarm manager sounds like quite a cool "out of the box" idea to me. Would be interesting to see how that performs! I went for some kind of scheduler implementation too. Lovely. – Tom Apr 09 '14 at 09:09
-1
@Override
protected String doInBackground(String... params) {
    Log.d(TAG, "type - " + params[0] + ", url = " + params[1] + ", name = " +   params[2]);


    downloadFile(params[1], params[2]);


    return null;
}

here is download method

URL url = new URI(Url.replace(" ", "%20")).toURL();
        URLConnection connection = url.openConnection();
        connection.setConnectTimeout(1000);
        int fileLength = connection.getContentLength();

        mSavePath = CommonUtilities.getFileSavePath(mContext, fileName, fileLength);
        Log.d(TAG, "*** saveFilePath - " + mSavePath);

        InputStream inputStream = connection.getInputStream();
        if (inputStream != null) {
            File file = new File(mSavePath);

            BufferedOutputStream bufferOutputStream = new   BufferedOutputStream(new FileOutputStream(file));
            byte byteArray[] = new byte[1024];
            int len = 0;
            long total = 0;

            while ((len = inputStream.read(byteArray)) != -1) {
                bufferOutputStream.write(byteArray, 0, len);
                total += len;
            }

            bufferOutputStream.flush();
            bufferOutputStream.close();
            inputStream.close();
        } else {
            Log.d(TAG, "*** inputStream is null");

        }
Amit
  • 391
  • 3
  • 15
  • Amit how have you possibly answered the question? You have just posted how to download a file, which is a really bad way of implementing the download of a score as the OP is trying to do! The OP is asking whether using an Async task is a good idea "worried about the instance created for AsynTask every 4'sec causes any problem" – Tom Apr 09 '14 at 07:09
  • You can use GCM so that if anything new score is available so that you can get your new scores downloaded using this method and you save your battery :) – Amit Apr 09 '14 at 07:10
  • Where do you say this in your answer? There's no code here that does that! And *even* if you used GCM, what if the score *did* update every four seconds? Then saving to disk is, again, a really bad idea when you don't need to! – Tom Apr 09 '14 at 07:11
  • yes it is a bad idea and it is also a bad idea to keep checking if anything new is available on server side(if it is using asynctask or any worker thread and executing it in every 4 sec) better to use GCM – Amit Apr 09 '14 at 07:14
  • I'm a little confused Amit. You're the one telling the OP to do it: `BufferedOutputStream(new FileOutputStream(file));` Best. – Tom Apr 09 '14 at 07:16
  • you should not download any data in your application whose size can increase :) – Amit Apr 09 '14 at 07:19
  • its not good idea to having worker thread in your app which is going to hit any url in 4-5 seconds even if you use timer your should not use frequently in few seconds :) – Amit Apr 09 '14 at 07:30
  • I'm confused. What do you mean by "whose size can increase"? Do you mean we're going to exhaust the heap? Could you explain why you think this is a concern? – Tom Apr 09 '14 at 07:32
  • And yes, it's not great having a thread clogged up with probably continuous http. But the lovely OP doesn't have some kind of server push set up, so she/he needs a solution for the immediate time. And if you have to have continuous http, a background thread has been the way to do it in Java as we both agree. The question is, *which* kind of concurrency... – Tom Apr 09 '14 at 07:34