Reputation: 270
I have made a library that makes a network call and fills a data class on success
data class someData(
val id: String,
val name: String,
)
I'm using moshi and retrofit for the network calls Once the network call is successful and the data class is filled, I need to send this to the app module
How is this done when we use internal data class and internal viewmodels? My library viewmodel should pass the data to the app viewmodel
The app uses a button to launch the library The library has a UI with jetpack compose, it collects information and makes the necessary network calls, and fills the data class on success How can the library close the compose UI and return the data?
Upvotes: 2
Views: 526
Reputation: 93601
The new "standard practice" way recommended by Google would be to create an ActivityResultContract in your library.
First, you need to make your data class Parcelable. This is most easily done using Parcelize (instructions here).
@Parcelize
data class SomeData(
val id: String,
val name: String,
)
In your library's activity, when you have created an instance of your SomeData class, you should set it as your activity result before finishing the activity:
val resultIntent = Intent().apply {
putExtra("someData", someDataInstance)
}
setResult(Activity.RESULT_OK, resultIntent)
finish()
Then create a contract for your library that launches your library's Activity, and extracts your data class from your activity's results. In this example, there is no required input for the library, so I'm just using Unit as the input type.
Note the return type should be nullable to handle the case where the user exits the library activity before finishing waiting for the fetched result.
class FetchSomeData: ActivityResultContract<Unit, SomeData?>() {
override fun createIntent(context: Context, unit: Unit) =
Intent(context, MyLibraryActivity::class.java)
override fun parseResult(resultCode: Int, result: Intent?) : SomeData? {
if (resultCode != Activity.RESULT_OK) {
return null
}
return result?.getParcelableExtra("someData")
}
}
Then users of your library will register the contract in a class property and use it in one of their button clicks, as explained in the contracts documentation. For example:
private val fetchSomeData = registerForActivityResult(FetchSomeData()) { someData: SomeData? ->
if (someData == null) {
// action was canceled
} else {
// do something with someData
}
}
//...
someButton.setOnClickListener {
fetchSomeData.launch()
}
Upvotes: 3