0

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?

avluis
  • 317
  • 5
  • 18
  • 1
    Have you tried using http://square.github.io/otto/. It is idea for what you want to do. – hoomi Sep 21 '15 at 20:53
  • @hoomi Looking over their docs and samples, I get the gist of it, but most is flying over my head at the moment - let me give it a try and see if I can work it out with otto. – avluis Sep 21 '15 at 21:02
  • 1
    Sure. It just makes your life much easier once you understand how it works. – hoomi Sep 21 '15 at 21:02
  • @hoomi OK - tried it, couldn't get around it. I can see what it is good for but I cannot wrap my head around how I can subscribe a class in my Activity to my fragment when the data is available. Sorry. Doesn't help that the samples I found only touch a few subjects. – avluis Sep 21 '15 at 23:36
  • @hoomi OK - Update! I took a few more stabs at it until I got my data to move about. I now have it where I need it - time to see if I can implement the rest of my services with this. – avluis Sep 22 '15 at 00:47
  • @hoomi And it works~ This is neat - not sure if the best solution, but I don't see an alternative at the moment, so this will do for now. This is what got me to understand Otto properly: http://www.cardinalsolutions.com/blog/2015/02/event-bus-on-android – avluis Sep 22 '15 at 01:25

0 Answers0