How to Get Results from an Intentservice Back into an Activity

How to get results from an IntentService back into an Activity?

You should look at creating your own ResultReceiver subclass in your activity. ResultReceiver implements Parcelable so can be passed from your Activity to your Service as an extra on the Intent.

You'll need to do something like this:

  1. Implement a subclass of ResultReceiver within your activity class. The key method to implement is onReceiveResult(). This method provides you a with Bundle of result data which can be used to pass whatever information you are retrieving in your Service. Simply unpack the data you need and use it to update your activity.

  2. In your activity, create a new instance of your custom ResultReceiver and add it to the Intent you use to start your service.

  3. In your Service's onStartCommand() method, retrieve the ResultReceiver passed in on the Intent and store it in a local member variable.

  4. Once your Service completes its work, have it call send() on the ResultReceiver passing whatever data you want to send back to the activity in a Bundle.

This is a pretty effective pattern and means you're not storing data in nasty static variables.

Start IntentService from Activity and refresh Activity when IntentService is finished

As an example, I use a ResultReceiver to call notifyDataSetChanged() on the adapter of my Activity (which extends ListActivity). It can be adapted to do whatever you need.

ResultReceiver code:

public class MyResultReceiver extends ResultReceiver {

private Context context = null;

protected void setParentContext (Context context) {
this.context = context;
}

public MyResultReceiver(Handler handler) {
super(handler);
}

@Override
protected void onReceiveResult (int resultCode, Bundle resultData) {

// Code to process resultData here

((BaseAdapter) ((ListActivity)context).getListAdapter()).notifyDataSetChanged();
}
}

MyActivity code:

public class MyActivity extends ListActivity {

private MyResultReceiver theReceiver = null;

...

private void callService () {
theReceiver = new MyResultReceiver(new Handler());
theReceiver.setParentContext(this);
Intent i = new Intent("com.mycompany.ACTION_DO_SOMETHING");

// Code to define and initialize myData here

i.putExtra("someData", myData);
i.putExtra("resReceiver", theReceiver);
startService(i);

}
}

IntentService code:

Bundle resultBundle = new Bundle();
ResultReceiver resRec = intent.getParcelableExtra("resReceiver");

// Do some work then put some stuff in resultBundle here

resRec.send(12345, resultBundle);

update data from intentservice on an activity

You can not use MainActivity instance like that in your Intent service code.
There are multiple approach to update UI from service like, LocalBroadcastReceivers, Messengers, BoundedService etc.

You can find an example to update UI from service using LocalBroadcastManager here

How to get Activity in Intent Service

I used some of the tricks for list control data binding. I solved with LayoutInflater. If I get layout inflater, I can fill the data to controls. Intent Service can get Layout Inflater. I send LayoutInflater from intent service to my DictionaryListAdapter class.

That's ok for me.

(FloatSomeService.java) Intent Service

public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
// Find Controls
LayoutInflater inflater = LayoutInflater.from(this);
viewFloat = inflater.inflate(R.layout.float_view, null);
listview = (ListView)viewFloat.findViewById(R.id.listDic);
this.generateData();

// *** Send Inflater to List Adapter
myAdapter = new DictionaryListAdapter((LayoutInflater)getBaseContext().getSystemService(LAYOUT_INFLATER_SERVICE), myListItem);
listview.setAdapter(myAdapter);
......................
windowManager.addView(viewFloat, parameters);}

(DictionaryListAdapter.java) List Adapter

public class DictionaryListAdapter extends BaseAdapter{
private LayoutInflater layoutInflater;
private ArrayList<HistoryListItem> myItems;
public DictionaryListAdapter(LayoutInflater inflater, ArrayList<DictionaryListItem> items){
this.layoutInflater = inflater;
this.myList = items;
}

public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
if (convertView == null) {
// don't need activity for layout inflater
convertView = this.layoutInflater.inflate(R.layout.history_list_item, null);
}
ImageView imgPerson = (ImageView)convertView.findViewById(R.id.imgPerson);
...........................
}}

How to return an object from an IntentService?

Does this remote API serialize the data in some way (JSON or XML)? Can you not hold off on the deserializing until it reaches the Activity?

Failing this I would see serialization as the best option. Parcelable is a specific type of serialization which, as you point out is a little more tricky to implementent but should be more performant if you are concerned about performance. Unless you are handling a huge amount of traffic, though, the serialization option shouldn't be too sluggish in my experience.

How to return ArrayList results from an IntentService

I switched over to using Parcelable (i.e., option 2 above), and it works fine now. I used the code from this accepted answer as a reference.

Still testing, but I'm pretty sure the change resolved the error I was getting by updating the adapter's underlying list off the UI thread. I have yet to try it for lists with > 100 elements, but so far so good. Thanks.



Related Topics



Leave a reply



Submit