0

This builds upon an earlier question, which is a PoC.

enter image description here

The above diagram shows the basic setup of the workings in my app.

In the real-time app, I am invoking the IntentService in the onOptionsItemSelected() method of a Fragment, like this:

@Override
public boolean onOptionsItemSelected(MenuItem item)
{ 
    ...
    ...
    Intent myServiceIntent = new Intent(getActivity(), MyService.class);
    getActivity().startService(myServiceIntent);
    ...
    ...
}

MyService downloads data from the cloud and saves them into a local SQLite database. Next, AsyncTasks in the same Fragment consume the data to update another Fragment. The key is, the AsyncTask should begin their doInBackground() after MyService is done.

The PoC worked with Service well, showing the ProgressBar and keeping the UI constantly updated with intermediate results through BroadcastReceivers. Please note the Service was called from AppCompatActivity, but in the real app, its called from a Fragment. The exact same setup fails, no ProgressBar, no interim updates. Log messages from the BroadcastReceivers show up after the AsyncTasks have completed.

The questions then are,

  • Do IntentServices block UI by nature, like AsyncTask get()? The PoC answer is NO, but in my real-time app, interim progress update fails.
  • How can an AsyncTask wait till an IntentService has finished?
  • Why are logs in the BroadcastReceiver displayed only after the AsyncTasks have finished?
  • This being such a common situation, is there a best practice to overcome this?

Pardon the verbosity, but hope the situation is clear. Please comment if there are ambiguities.

Please note that I've seen this answer among others, but none really suit me, unfortunately.

Many thanks in advance!

Narayana J
  • 307
  • 5
  • 17

2 Answers2

1

Do IntentServices block UI by nature, like AsyncTask get()?

No they do not, that is the whole point of an IntentService to do things in the background

How can an AsyncTask wait till an IntentService has finished?

there are a few ways but an easy way would be to use a BroadcastReceiver in your activity that holds your fragment and have your activity trigger the fragment/s update. Remember a fragment should NOT talk to another fragment, your activity should be the one delegating information between the fragments.

why your BroadcastReceiver does not work in your real app I cannot answer with the information given you may be just missing something when you change it over. I use BroadcastReceivers with IntentServices all the time with no problems

tyczj
  • 71,600
  • 54
  • 194
  • 296
  • Thanks @tyczj! You said, "Remember a fragment should NOT talk to another fragment," - My `BroadcastReceiver`s and service starters are in a fragment, so sibling fragments _are_ talking. Could that be a reason why I am not seeing interim progress updates? Is it worth the exercise to move `BroadcastReceiver`s and service starters to the host `Activity`? – Narayana J Apr 07 '16 at 16:09
  • 1
    While I guess you could consider using a broadcast receiver as talking to 2 fragments thats not what I mean really. What I am talking about is one fragment has a direct reference to another which is bad. I personally would move your broadcast receivers to your holding activity since IMO that would make for much cleaner code – tyczj Apr 07 '16 at 16:14
0

Thanks @tyczj for the crisp and succinct answers!

Just to formally complete...

Why are logs in the BroadcastReceiver displayed only after the AsyncTasks have finished?

Though obscure, it was very much my mistake, duh. (Only) debugging reveals.

This being such a common situation, is there a best practice to overcome this?

The best practice IMHO is, to practice. However, these are points I understood (the hard way):

  • IntentService over AsyncTask for background work of more than 5 seconds
  • LocalBroadcastManager with BroadcastReceiver to show progress updates from IntentService and to make other quicker background threads wait upon.
Narayana J
  • 307
  • 5
  • 17