Search code examples
androidandroid-fragmentsandroid-activityservice

Best way to share same data instance between an Activity, Fragment and Service?


I am an amateur android developer and I making a Music Player app and I need have to have the same object instance (Song object) in my Activity, Fragment and Service and all of them are capable of manipulating the state of object. User can play/pause/next/prev a song and all of them needs to show the same current song information and state of the song if it is PAUSED or PLAYING.

My Activity can change the song state through the bottom layout that is persistent on all fragments. My Fragments can change the song state through choosing/pausing songs through the playlist page. My Service can change the song state through the notification bar by pausing/resuming/next/prev a song.

I have trouble thinking of a solution on where and how to store the object instance. I thought of having them all have a Song object instance and just update the value through sending broadcasts but I don't think this is the best solution and looks pretty sloppy.

The song URLs to be played are also retrieved from a server. Where is the best place to make the API calls?

It would be greatly appreciated if anyone can suggest a better approach on how to do this. Thank you!

Regards,


Solution

  • You can create a ViewModel with activity scope, that will be shared between the Fragment/Activity/Service.

    class AudioPlayerViewModel: ViewModel {
        val songLiveData = MutableLiveData<Song>()
        
        fun playSong() {
            // Todo your logic
        }
        
        fun stopSong() {
            // Todo your logic
        }
        
        .
        .
        .
    }
    

    Every change you will do to your song will be done through the ViewModel and the Fragment/Activity/Service will observe to changes happening in the songLiveData and update the UI accordingly.

    As for network requests I suggest you take a look at the retrofit library. A common practice is to use the Repository pattern that will hold all the network and DB calls after that you can get an instance of the repository inside your ViewModel and execute that Network call. You can either use coroutines or RxJava to handle the threading.

    To summarize:

    Activity/Fragment/View/Services...

    Responsible for UI interaction the observe data from ViewModels and do UI changes accordingly to that Data.

    ViewModel

    Have the responsibility of an interactor between the network layer and what the users see. They modify the data so the UI can stay dumb and not hold any logic.

    Repository

    Responsible for API & DB calls.