I hope to explain this as best as I can, as I am not an expert on the subject:
I have two children in child Services; MusicProvider and MusicService - both implement IBinder but neither agree on how they do things:
MusicService takes care of setting up a MediaPlayer and keeping it running while actively playing, while MusicProvider is a JSON parser that eventually provides a SongList as an ArrayList (and shares it with whoever needs it, but after some time).
MusicService does not implement nor care for that matter about MusicProvider, but their relationship will be known in a second.
MusicProvider runs its JSON parsing in a background AsyncTask (called by retrieveMediaAsync(...)) and relies on a callback/listener to notify anyone who cares about him once he has gathered his children (songs).
In my search to find better care of these two, while keeping them alive when their world was killed in a series of rotations, I looked into other ways of keeping them alive, and got to know RetainedFragment from a close friend.
RetainedFragment will keep my children alive during world killing rotations, along with any other data they might need to work. So I went with that, which worked great until I tried to talk to my child, MusicProvider.
See, RetainedFragment implemented MusicProvider's callbacks, and I am not sure how I can get to listen in as I try to manage my RetainedFragment - so my methods don't fire off when MusicProvider is done doing its work. Any tips?
For those that don't care for the story, I have something like this:
public class RetainedFragment extends Fragment implements MusicProvider.Callback {
private boolean isServiceBound = false;
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.MusicBinder musicService = (MusicService.MusicBinder) service;
musicService.getMusicService();
isServiceBound = true;
LogHelper.i(TAG, isServiceBound());
}
@Override
public void onServiceDisconnected(ComponentName name) {
isServiceBound = false;
}
};
private MusicProvider mMusicProvider;
private boolean isProviderBound = false;
private final ServiceConnection mProviderConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicProvider.MusicBinder musicBinder = (MusicProvider.MusicBinder) service;
mMusicProvider = musicBinder.getMusicProvider();
isProviderBound = true;
LogHelper.i(TAG, isProviderBound());
retrieveMediaFromProvider();
}
@Override
public void onServiceDisconnected(ComponentName name) {
isProviderBound = false;
}
};
private void retrieveMediaFromProvider() {
if (isProviderBound) {
mMusicProvider.retrieveMediaAsync(this);
}
}
private static List<Song> sSongList = new ArrayList<>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// retain this fragment
setRetainInstance(true);
}
@Override
public void onStop() {
super.onStop();
if (isServiceBound) {
getActivity().unbindService(mServiceConnection);
isServiceBound = false;
}
if (isProviderBound) {
getActivity().unbindService(mProviderConnection);
isProviderBound = false;
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (isServiceBound) {
getActivity().unbindService(mServiceConnection);
isServiceBound = false;
}
if (isProviderBound) {
getActivity().unbindService(mProviderConnection);
isProviderBound = false;
}
}
public boolean isServiceBound() {
return isServiceBound;
}
public boolean isProviderBound() {
return isProviderBound;
}
public List<Song> getSongList() {
return sSongList;
}
@Override
public void onMusicCatalogReady(boolean success) {
if (success) {
sSongList = mMusicProvider.getSongs();
LogHelper.i(TAG, sSongList);
LogHelper.i(TAG, "onMusicCatalogReady");
}
}
@Override
public void onMusicCatalogFailure(boolean failure) {
if (failure) {
LogHelper.i(TAG, "onMusicCatalogFailure");
}
}
}
The plan is to add this fragment to any activity that may need these two services, but one of those services only provides its data when it is ready (it does cache the data so it is fast at it) and informs via its callback.
How can I extend the MusicProvider's callback from the RetainedFragment and onto any attaching Activity?
I am thinking of adding an interface to RetainedFragment that extends MusicProvider.Callback, which will require me to implement in the calling activity, but I'm not too sure how to do that, nor if it will work - any takes?