0

In my acivity, i need to run two background service.

main background service:

class loadingTask extends AsyncTask<Void, Void,Void> {

      @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        pd = ProgressDialog.show(context, "", "Chargement en cours..", true, false);
        super.onPreExecute();
    }


    @Override
    protected void onPostExecute(Void result) {
         // TODO Auto-generated method stub
        super.onPostExecute(result);
        pd.dismiss();
    }

    ...

    @Override
    protected Void doInBackground(Void... params) {
        // TODO Auto-generated method stub
        getxml = Util.CallWebService("");
        return null;
    }
}

Second background service.

class mloadingTask extends AsyncTask<String, Void, String> {

    protected String doInBackground(String... urls) {

        SAXHelper sh = null;
        try {
            sh = new SAXHelper(urls[0]);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        sh.parseContent("");
        return "";

    }

    protected void onPostExecute(String s) {
        pd.dismiss();

    }
}

In my onCreate() method I want to call the first background and when it finished loading the second background service starts. Part of my background service is as follows.

AsyncTask<Void, Void,Void> loadTask = new loadingTask().execute();

    if(loadTask.getStatus()==AsyncTask.Status.FINISHED){

         new mloadingTask().execute(getxml);

         System.out.println("getxml: "+getxml);
    }

However the second background service doesn't seem to start. i am not getting the a print also. I think I miss a step or android doesn't allow more than one background service in the same activity. A help please.

sandrstar
  • 12,503
  • 8
  • 58
  • 65
yakusha
  • 817
  • 7
  • 13
  • 21
  • After you execute loadTask, you instantly check if it is finished. If you do anything that takes more then 50ms, it will never pass the check. You should create a callback of some sort(interfaces work nicely for this) – Joey Roosing Apr 03 '13 at 09:48
  • can you give me an example please ? – yakusha Apr 03 '13 at 09:49

2 Answers2

0

AsyncTask is Asynchronous as its name suggest. You need to call your 2nd AsyncTask in onPostExecute of your 1st AsyncTask

OR

Loop and wait till AsyncTask is finished in your activity, but it may take more time and you can get Application Not Responding message.

As soon as you call execute() method, control comes to next statement which loadTask.getStatus(). As task is just started, loadTask.getStatus() will not return FINISH and your 2nd task is never getting executed.

Amit
  • 1,365
  • 8
  • 15
  • There is a force close (concurrent error ) when i put the .execute() in the postexcute method of first asynctask. That's why i am trying to find an alternative to run the second background service. – yakusha Apr 03 '13 at 09:56
  • In that case, pass your activity object (this) to your 1st async task and in onPostExecute, call a method which launch your 2nd AsyncTask using activity object – Amit Apr 03 '13 at 10:01
  • can you give me an example ? or a tutorial – yakusha Apr 03 '13 at 10:17
  • Add a member variable mActivityContext in your "loadingTask" class. Before calling execute(), initialize loadingTask object and set activity context. Create a function onLoadingTaskFinish() in your activity. In onPostExecute of your loadingTask class, call mActivityContext.onLoadingTaskFinish(). onLoadingTaskFinish will call another AsyncTask – Amit Apr 03 '13 at 10:27
0
AsyncTask<Void, Void,Void> loadTask = new loadingTask().execute();

if(loadTask.getStatus()==AsyncTask.Status.FINISHED){

  new mloadingTask().execute(getxml);

  System.out.println("getxml: "+getxml);
}

there is a 99% chance that the if() block will never pass. You first execute the first asyncTask named loadTask and RIGHT after check if it finished. Small chance that it actually finishes by then.

The easy approach:

Use only one async task. You want to finish asyncTask 1 and then fire asyncTask 2, its exactly the same as having only one asyncTask doing both operations.

class loadingTask extends AsyncTask<Void, Void,Void> {

      @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        pd = ProgressDialog.show(context, "", "Chargement en cours..", true, false);
        super.onPreExecute();
    }


    @Override
    protected void onPostExecute(Void result) {
         // TODO Auto-generated method stub
        super.onPostExecute(result);
        pd.dismiss();
    }

    ...

    @Override
    protected Void doInBackground(Void... params) {
        // TODO Auto-generated method stub
        getxml = Util.CallWebService("");

        SAXHelper sh = null;
        try {
            sh = new SAXHelper(urls[0]);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        sh.parseContent("");
        return null;
    }
}

The difficult approach:

How I solve this kind of thing is(our situation is different, but it should do)

Create an interface, with one method. for example:

public interface OnDataChangedListner {
    void dataChanged(Class listener);
}

Then somewhere (i use my repository classes) write a method to add and remove entires to a list of OnDataChangedListener interfaces

private ArrayList<OnDataChangedListner> mOnDataChangedListners;

public void addOnDataChangedListner(OnDataChangedListner onDataChangedListner){
    synchronized (mOnDataChangedListners){
        mOnDataChangedListners.add(onDataChangedListner);
    }
}

public void removeOnDataChangedListner(OnDataChangedListner onyDataChangedListner){
    if (mOnDataChangedListners != null){
        synchronized (mOnDataChangedListners){
            for (Iterator<OnDataChangedListner> it = mOnDataChangedListners.iterator(); it.hasNext();) {
                OnDataChangedListner listener = it.next();
                if (listener .equals(onDataChangedListner))
                    it.remove();
            }
        }
    }
}

This might be overkill. But this example should help you with updating the UI while your tasks are running. A free extra! :))

With the above code in place, create an onDataChanged() method in the same class where u defined the add and remove listener methods.

In that code call a handler

// Need handler for callbacks to the UI thread
final static Handler mHandler = new Handler();

// Create runnable for posting
final Runnable mNotifyDataChanged = new Runnable() {
    public void run() {
        if (mOnDataChangedListners != null){
            synchronized (mOnDataChangedListners){
                for (Iterator<OnDataChangedListner> it = mOnDataChangedListners.iterator(); it.hasNext();) {
                    OnDataChangedListner listener = it.next();
                    if (listener  != null)
                        listener.dataChanged(this.getClass());
                    else
                        it.remove();
                }
            }
        }
    }
};

/**
 * will notify registerred delegates on the main (UI) thread
 */
public void notifyDataChanged(){
    mHandler.post(mNotifyDataChanged);
}

Ok, so I ended up giving out an entire sample. Where you place this code is upto you. But when you call notifyDataChanged() it will fire the handler, which in turn will loop trough all current registered listeners for this class

then in turn it will call the listeners datachanged method.

To make this all work, all you have to do is have a class implement the interface

call addOnDataChangedListener(this);

and implement the method provided in the interface.

Note that this is deffinetly not the easiest way to do things. I don't know what the easiest way to do what you want is. I never have been in that situation before.

but you can execute the second task in the implemented method. Should work..

Joey Roosing
  • 2,145
  • 5
  • 25
  • 42
  • can you help me in the chat room please ? – yakusha Apr 03 '13 at 10:11
  • I wrote an entire example here.. its not very simple, but you can almost copy and paste it and it should work. Have you ever worked with listeners/interfaces? – Joey Roosing Apr 03 '13 at 10:19
  • Most of it is java, there is very little android specific code here – Joey Roosing Apr 03 '13 at 10:20
  • eclipse says "mOnDataChangedListners cannot be resolved to a variable" – yakusha Apr 03 '13 at 10:23
  • private ArrayList mOnDataChangedListners; OnDataChangedListener is the interface you should define somewhere(seperate file) If it won't work I may have a typo somewhere – Joey Roosing Apr 03 '13 at 10:24
  • last thing now onRepositoryDataChangedListner cannot be resolved to a variable and onDataChangedListner cannot be resolved to a variable – yakusha Apr 03 '13 at 10:29
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/27472/discussion-between-joey-roosing-and-yakusha) – Joey Roosing Apr 03 '13 at 10:30