Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
408 views
in Technique[技术] by (71.8m points)

android - Pass integer to ViewModel when using HILT

I am trying to figure out how to pass an integer from a fragment to a viewmodel while using hilt. I have ready that viewmodel factories can be used for this, I am not sure how this would be done using DI.

In the code below, I am trying to figure out how I can pass albumId to the viewModel. The albumId will be used when fetching data from an API endpoint.

Fragment

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    // Inflate the layout for this fragment
    val view = inflater.inflate(R.layout.fragment_album_details, container, false)

    val albumId = arguments?.getInt("album_id")

    viewModel.songs.observe(viewLifecycleOwner) {
        view.song_recyclerview.apply {
            layoutManager = LinearLayoutManager(this.context)
            adapter = SongAdapter(viewModel.songs)
        }
    }
    return view
}

ViewModel

class SongViewModel @ViewModelInject constructor(
    songRepo: SongRepository,
    @Assisted savedStateHandle: SavedStateHandle
) : ViewModel(), LifecycleObserver {

    val songs: LiveData<List<Song>> = songRepo.getSongs(1)
}

Repository

class SongRepository constructor(
    private val musicService: MusicService
)
{
    fun getSongs(album_id: Int): LiveData<List<Song>> {
        val data = MutableLiveData<List<Song>>()
        musicService.getAlbumTracks(album_id).enqueue(object : Callback<List<Song>> {
            override fun onResponse(call: Call<List<Song>>, response: Response<List<Song>>) {
                data.value = response.body()
            }

            override fun onFailure(call: Call<List<Song>>, t: Throwable) {
            }
        })
        return data
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I was finally able to figure out a solution to the problem. I added a field to the viewmodel, and a method to set a value for that field. Basically, I call viewModel.start(int) then call viewModel.songs.

ViewModel

class SongViewModel @ViewModelInject constructor(
    songRepo: SongRepository,
    @Assisted savedStateHandle: SavedStateHandle
) : ViewModel(), LifecycleObserver {

    private val _id = MutableLiveData<Int>() // int field
    private val _songs = _id.switchMap { id -> 
        songRepo.getSongs(id)
    }
    val songs: LiveData<List<Song>> = _songs
    fun start(id: Int) { // method to update field
        _id.value = id
    }
}

Fragment

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    // get data from bundle and pass to start()
    arguments?.getInt(("album_id"))?.let { viewModel.start(it)}

    viewModel.songs.observe(viewLifecycleOwner) {
        view.song_recyclerview.apply {
            layoutManager = LinearLayoutManager(this.context)
            adapter = SongAdapter(viewModel.songs)
        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...