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:
Implement a subclass of
ResultReceiver
within your activity class. The key method to implement isonReceiveResult()
. This method provides you a withBundle
of result data which can be used to pass whatever information you are retrieving in yourService
. Simply unpack the data you need and use it to update your activity.In your activity, create a new instance of your custom
ResultReceiver
and add it to theIntent
you use to start your service.In your
Service
'sonStartCommand()
method, retrieve theResultReceiver
passed in on theIntent
and store it in a local member variable.Once your
Service
completes its work, have it callsend()
on the ResultReceiver passing whatever data you want to send back to the activity in aBundle
.
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
Android Get Application's 'Home' Data Directory
Firebase Console: How to Specify Click_Action for Notifications
Remove Animation/Shifting Mode from Bottomnavigationview Android
How to Make Space Between Linearlayout Children
Android Volley Imageloader - Bitmaplrucache Parameter
Android: Is There Any Free PDF Library for Android
How to Play .Mp4 Video in Videoview in Android
Gradle Android Build for Different Processor Architectures
How to Play an Audio File on a Voice Call in Android
Android Studio and Android.Support.V4.App.Fragment: Cannot Resolve Symbol
How to Be Notified When a Snackbar Has Dismissed Itself
Generate Javadocs with Android Gradle Plugin
How to Set Status Bar Background as Gradient Color or a Drawable in Android
Coordinatorlayout Using The Viewpager's Recyclerview