4

I made Service that runs on the background collecting data from internet using AsyncTask and storing them in Shared Preferences. Even though the work is done in AsyncTask it still freezes my main activity.

Here is the code for Service:

public class GetterService extends Service {

    SharedPreferences.Editor editor;
    HashMap<Integer,String> links = new HashMap<Integer,String>();

    @Override
    public void onCreate() {
        editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
        populateLinks();
    }

    private void populateLinks(){
        // Here I add links to HashMap
    }

    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(this, "GetterService ON BIND", Toast.LENGTH_LONG).show();
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(this, "GetterService ON DESTROY", Toast.LENGTH_LONG).show();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        doTasks();

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Toast.makeText(this, "GetterService ON UNBIND", Toast.LENGTH_LONG).show();
        return super.onUnbind(intent);
    }

    private void doTasks(){
        for (Integer in : links.keySet()) {

            Document doc = null;

            try {
                doc = new NetTask().execute(links.get(in)).get();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            if (doc != null) {
                Elements names = doc.select("strong, li");

                if(names != null && names.size() > 0) {
                    for (int j = 0; j < names.size(); j++) {
                        editor.putString("header"+j, names.get(j).text().toString());
                    }
                }
                editor.commit();
            }
        }   
    }

    public class NetTask extends AsyncTask<String, Integer, Document>
    {
        @Override
        protected Document doInBackground(String... params)
        {
            Document doc = null;
            try {
                doc = Jsoup.connect(params[0]).timeout(5000).get();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return doc;
        }
    }
}

and here is how I start the service from main activity:

Intent startServiceIntent = new Intent(this, GetterService.class);
        this.startService(startServiceIntent);
Rohit Malish
  • 3,209
  • 12
  • 49
  • 67

4 Answers4

8

Even though the work is done in AsyncTask it still freezes my main activity.

You are using get():

doc = new NetTask().execute(links.get(in)).get();

And get() blocks the UI thread until the AsyncTask has completed, to me this method defeats the purpose of using a AsyncTask...


You should move this logic:

if (doc != null) {
    Elements names = doc.select("strong, li");

    if(names != null && names.size() > 0) {
        for (int j = 0; j < names.size(); j++) {
            editor.putString("header"+j, names.get(j).text().toString());
        }
    }
    editor.commit();
}

Inside your NetTask's onPostExecute() method and remove get(). Now your AsyncTask won't bind-up the main thread.

Sam
  • 86,580
  • 20
  • 181
  • 179
  • this did help, kind of. The only thing now is that main activity freezes when I try to go to another activity while service is doing tasks. Any idea why? – Rohit Malish Dec 10 '12 at 21:12
  • Have you tried cancelling the active download inside `GetterService#onDestroy()`? [Android - Cancel AsyncTask Forcefully](http://stackoverflow.com/q/4748964/1267661) – Sam Dec 10 '12 at 21:49
  • No, but I already found out what is causing this problem and I have opened new guestion for it. Thanks though. – Rohit Malish Dec 10 '12 at 21:51
4

It's because of the

new NetTask().execute(links.get(in)).get();

call.

AsyncTask.get() blocks until the async call has been completed. To be asynchronous you need to implement

onPostExecute() 

and process the results there.

fedepaol
  • 6,834
  • 3
  • 27
  • 34
0

Don't call get(), just call execute(). Implement and overridden onPostExecute() to take a Document object as a parameter. onPostExecute() is called automatically when doInBackground() returns. Code in onPostExecute() is executed on the UI thread, so you can interact with the UI that way.

I suggest you take a look at the AsyncTask section in this document, http://developer.android.com/guide/components/processes-and-threads.html and the AsyncTask API page here, http://developer.android.com/reference/android/os/AsyncTask.html.

jsimon
  • 577
  • 6
  • 17
0

I had the similar problem and figured out what's going on. This code will not freeze UI, but if you put 'for loop' and sleep inside onProgressUpdate, then UI will be frozen during the process.

public class Karaoke extends AsyncTask<Void, Integer, Void> {
    private Handler mHandler = new Handler(Looper.getMainLooper());
    protected Void doInBackground(Void... urls) {
        animating = true;
        {
            for (int i = 0;i < 6; i++)
            {
                publishProgress(i);
                try
                {
                    Thread.sleep(1000);
                    publishProgress(i);
                }
                catch (Exception xx){
                }
            }
        }
        animating = false;
        return null;
    }
    @Override
    protected void onProgressUpdate(Integer... values) {
        if (light)
        {
            light = false;
            iv_array[findview(egtxts[values[0]].getText() + "")].setImageResource(onpress);
        }
        else
        {
            light = true;
            iv_array[findview(egtxts[values[0]].getText() + "")].setImageResource(onup);
        }
    }

    protected void onPostExecute(Long result) {
        //showDialog("Downloaded " + result + " bytes");
    }
}
Vitas
  • 2,307
  • 2
  • 12
  • 5