Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passing the arguments of a fragment if mavericks:arg is not available #661

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import kotlin.reflect.KProperty
*/
@Suppress("FunctionName")
@InternalMavericksApi
fun <T : Fragment> T._fragmentArgsProvider(): Any? = arguments?.get(Mavericks.KEY_ARG)
fun <T : Fragment> T._fragmentArgsProvider(): Any? = arguments?.get(Mavericks.KEY_ARG) ?: arguments

/**
* Gets or creates a ViewModel scoped to this Fragment. You will get the same instance every time for this Fragment, even
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,58 @@ package com.airbnb.mvrx.dogs
import android.os.Bundle
import android.view.View
import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.airbnb.mvrx.Mavericks
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.MavericksView
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.activityViewModel
import com.airbnb.mvrx.args
import com.airbnb.mvrx.dogs.databinding.DogDetailFragmentBinding
import com.airbnb.mvrx.dogs.views.DogDetailFragmentHandler
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.viewbinding.viewBinding
import com.airbnb.mvrx.withState

class DogDetailFragment : Fragment(R.layout.dog_detail_fragment), MavericksView, DogDetailFragmentHandler {
private val binding: DogDetailFragmentBinding by viewBinding()
private val viewModel: DogViewModel by activityViewModel()
private val dogId: Long by args()
private val viewModel: DogDetailViewModel by fragmentViewModel()
private val dogViewModel: DogViewModel by activityViewModel()

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding.handler = this
}

override fun onLoveClicked() {
viewModel.loveDog(dogId)
withState(viewModel) {
dogViewModel.loveDog(it.dogId)
}
findNavController().popBackStack()
}

override fun invalidate() = withState(viewModel) { state ->
binding.dog = state.dog(dogId) ?: error("Cannot find dog with id $dogId")
when (state.dog) {
is Fail -> {
binding.progressBar.hide()
binding.error.isVisible = true
binding.error.text = state.dog.error.localizedMessage
}
is Loading, Uninitialized -> {
binding.progressBar.show()
binding.error.isVisible = false
}
is Success -> {
binding.progressBar.hide()
binding.error.isVisible = false
binding.dog = state.dog()
}
}
}

companion object {
fun arg(dogId: Long) = bundleOf(Mavericks.KEY_ARG to dogId)
const val ARG_DOG_ID = "dogId"
fun arg(dogId: Long) = bundleOf(ARG_DOG_ID to dogId)
}
}
16 changes: 16 additions & 0 deletions sample-dogs/src/main/java/com/airbnb/mvrx/dogs/DogDetailState.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.airbnb.mvrx.dogs

import android.os.Bundle
import com.airbnb.mvrx.Async
import com.airbnb.mvrx.MavericksState
import com.airbnb.mvrx.PersistState
import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.dogs.data.Dog

data class DogDetailState(
@PersistState
val dogId: Long,
val dog: Async<Dog> = Uninitialized,
) : MavericksState {
constructor(arguments: Bundle) : this(dogId = arguments.getLong(DogDetailFragment.ARG_DOG_ID))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.airbnb.mvrx.dogs

import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.MavericksViewModelFactory
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.ViewModelContext
import com.airbnb.mvrx.dogs.data.DogRepository
import com.airbnb.mvrx.dogs.utils.MvRxViewModel

class DogDetailViewModel(
initialState: DogDetailState,
private val dogRepository: DogRepository
) : MvRxViewModel<DogDetailState>(initialState) {

init {
withState {
getDog(it.dogId)
}
}

private fun getDog(dogId: Long) {
dogRepository.getDog(dogId)
.doOnSubscribe { setState { copy(dog = Loading()) } }
.subscribe { dog ->
dog?.let {
setState { copy(dog = Success(it)) }
} ?: setState { copy(dog = Fail(Throwable("Dog $dogId not found :("))) }
}.disposeOnClear()
}

companion object : MavericksViewModelFactory<DogDetailViewModel, DogDetailState> {

override fun create(viewModelContext: ViewModelContext, state: DogDetailState): DogDetailViewModel {
val dogRepository = viewModelContext.app<DogApplication>().dogsRepository
return DogDetailViewModel(state, dogRepository)
}
}
}
128 changes: 68 additions & 60 deletions sample-dogs/src/main/java/com/airbnb/mvrx/dogs/data/DogRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,67 +8,75 @@ import io.reactivex.schedulers.Schedulers
import java.util.concurrent.TimeUnit

class DogRepository {
fun getDogs() = Observable.fromCallable<List<Dog>> {
Thread.sleep(2000)
listOf(
Dog(
44365525,
"Turbo",
"Catahoula Leopard Dog Mix",
"https://dl5zpyw5k3jeb.cloudfront.net/photos/pets/44365525/3/?bust=1554156953&width=1080",
"Meet Turbo: Tank and Turbo are two gorgeous Catahoula mix boys who love nothing more than running and playing. These guys are approximately 9 weeks old and currently weigh around 13 pounds each. They are a good medium-large breed dog, and should grow to be around 60-70 pounds. Catahoulas have beautiful markings and these two are no different. The breed is known for being independent working dogs. Catahoulas require firm guidance and early socialization, as they can be independent, territorial, and protective. Once they know their place in the family unit, they are affectionate, loyal, and gentle."
),
Dog(
40037002,
"Jules",
"Terrier, Pit Bull Mix",
"https://cdn3-www.dogtime.com/assets/uploads/gallery/pit-bull-dog-breed-pictures/pit-bull-dog-breed-picture-1.jpg",
"His name is Jules and he is named after his favorite author Jules Verne. Jules is a happy boy who love nothing more than to hang out indoors with you, and while he may not always want to take a 'Journey to the Center of the Earth', he'll be just as happy if you read it to him or watch the film together! He enjoys good company and sun bathing, weather permitting. You don't have to travel \"20,000 leagues Under The Sea\" to meet him, you can find him at the SPCA!"
),
Dog(
39936816,
"Pearl",
"Shepherd Mix",
"https://www.sfspca.org/sites/default/files/styles/480_width/public/images/animals/39936816-120fca18.jpg",
"There's no shell around this Pearl! She's all the way out. Pearl is a very active and enthusiastic pup. While technically an adolescent pup, she's still got lots to learn. She adores being with people, plays fetch like a champ and can't wait to meet new folks and new dogs too. Pearl will thrive in a home with folks who have a more flexible schedule as she's very social and doesn't particularly like being alone for long periods of time. Lots of exercise and mental enrichment will help her grow into her very best self! Are you looking for a darling, active, friendly, snuggly, active, social and active companion? Come meet Pearl to see what all that looks like in one dog!"
),
Dog(
40379134,
"Maya",
"German Shepherd Mix",
"https://www.sfspca.org/sites/default/files/styles/480_width/public/images/animals/40379134-a547eac3.jpg",
"She is named after an ancient civilization, but there is nothing old and stuffy about this active girl. Meet Maya, a bouncy girl who is loaded with love and energy. Maya loves being active and she will always be ready to take you up on an offer to go for a walk. She will hope you bring a ball along with you since she is quite fond of chasing them. She is super affectionate and she loves getting treats. Maya needs to live in an active household where she can get lots of exercise. Come by and toss some balls around with Maya today."
),
Dog(
40706214,
"Victor",
"Australian Cattle Dog",
"https://www.sfspca.org/sites/default/files/styles/480_width/public/images/animals/40706214-5b51f8de.jpg",
"I'm a curious pup looking for adopters who will commit to continuing my puppy education and socialization. Ready for a home with snuggles and playtime and lots of puppy-love, I would love to attend puppy socials and meet other young dogs to grow in skills and confidence. Ask a staff member or check our website for details/dates of our Puppy Parent Orientation (free) class to learn how you can be my best family ever and receive 50% off my adoption fee! (PPO must be attended prior to adoption.)"
),
Dog(
39822990,
"Wonder",
"Shepherd Mix",
"https://www.sfspca.org/sites/default/files/styles/480_width/public/images/animals/39822990-628b4657.jpg",
"Have you ever wondered if there's a dog out there that's perfect for you? Wonder no more because it's probably our handsome Wonder dog! Wonder is his name and pondering the universal questions is his game. Ha! Wonder is a young, active, strong fellow, who prefers to take introductions slow and cautiously. He is hoping to find a forever home in a quieter, low dog-trafficked, neighborhood with experienced adopters. Wonder loves his own people very much and isn't too keen on sharing them with others, so he is hoping to find a special someone or two someones with whom to wander through the days ahead. Why not wander down to meet Wonder today!"
),
Dog(
44373538,
"Fuzzy",
"Terrier Mix",
"https://dl5zpyw5k3jeb.cloudfront.net/photos/pets/44373538/1/?bust=1554262696&width=1080",
"Fuzzy is a male Terrier mix and he's about a whole 8 weeks hold, which means plenty of mischief and fun trying to explore the world around him. And that means he should be finding his new forever home really soon so that he'll have fun getting to know people, places, toys, and maybe even other fur kids like him.\n" +
"\nDon't wait, these puppies don't last long..."
),
Dog(
44371030,
"Happy",
"Golden Retriever",
"https://thehappypuppysite.com/wp-content/uploads/2017/12/puppy2.jpg",
"What's not to love about a Golden Retriever!"
)

private val dogs: List<Dog> = listOf(
Dog(
44365525,
"Turbo",
"Catahoula Leopard Dog Mix",
"https://dl5zpyw5k3jeb.cloudfront.net/photos/pets/44365525/3/?bust=1554156953&width=1080",
"Meet Turbo: Tank and Turbo are two gorgeous Catahoula mix boys who love nothing more than running and playing. These guys are approximately 9 weeks old and currently weigh around 13 pounds each. They are a good medium-large breed dog, and should grow to be around 60-70 pounds. Catahoulas have beautiful markings and these two are no different. The breed is known for being independent working dogs. Catahoulas require firm guidance and early socialization, as they can be independent, territorial, and protective. Once they know their place in the family unit, they are affectionate, loyal, and gentle."
),
Dog(
40037002,
"Jules",
"Terrier, Pit Bull Mix",
"https://cdn3-www.dogtime.com/assets/uploads/gallery/pit-bull-dog-breed-pictures/pit-bull-dog-breed-picture-1.jpg",
"His name is Jules and he is named after his favorite author Jules Verne. Jules is a happy boy who love nothing more than to hang out indoors with you, and while he may not always want to take a 'Journey to the Center of the Earth', he'll be just as happy if you read it to him or watch the film together! He enjoys good company and sun bathing, weather permitting. You don't have to travel \"20,000 leagues Under The Sea\" to meet him, you can find him at the SPCA!"
),
Dog(
39936816,
"Pearl",
"Shepherd Mix",
"https://www.sfspca.org/sites/default/files/styles/480_width/public/images/animals/39936816-120fca18.jpg",
"There's no shell around this Pearl! She's all the way out. Pearl is a very active and enthusiastic pup. While technically an adolescent pup, she's still got lots to learn. She adores being with people, plays fetch like a champ and can't wait to meet new folks and new dogs too. Pearl will thrive in a home with folks who have a more flexible schedule as she's very social and doesn't particularly like being alone for long periods of time. Lots of exercise and mental enrichment will help her grow into her very best self! Are you looking for a darling, active, friendly, snuggly, active, social and active companion? Come meet Pearl to see what all that looks like in one dog!"
),
Dog(
40379134,
"Maya",
"German Shepherd Mix",
"https://www.sfspca.org/sites/default/files/styles/480_width/public/images/animals/40379134-a547eac3.jpg",
"She is named after an ancient civilization, but there is nothing old and stuffy about this active girl. Meet Maya, a bouncy girl who is loaded with love and energy. Maya loves being active and she will always be ready to take you up on an offer to go for a walk. She will hope you bring a ball along with you since she is quite fond of chasing them. She is super affectionate and she loves getting treats. Maya needs to live in an active household where she can get lots of exercise. Come by and toss some balls around with Maya today."
),
Dog(
40706214,
"Victor",
"Australian Cattle Dog",
"https://www.sfspca.org/sites/default/files/styles/480_width/public/images/animals/40706214-5b51f8de.jpg",
"I'm a curious pup looking for adopters who will commit to continuing my puppy education and socialization. Ready for a home with snuggles and playtime and lots of puppy-love, I would love to attend puppy socials and meet other young dogs to grow in skills and confidence. Ask a staff member or check our website for details/dates of our Puppy Parent Orientation (free) class to learn how you can be my best family ever and receive 50% off my adoption fee! (PPO must be attended prior to adoption.)"
),
Dog(
39822990,
"Wonder",
"Shepherd Mix",
"https://www.sfspca.org/sites/default/files/styles/480_width/public/images/animals/39822990-628b4657.jpg",
"Have you ever wondered if there's a dog out there that's perfect for you? Wonder no more because it's probably our handsome Wonder dog! Wonder is his name and pondering the universal questions is his game. Ha! Wonder is a young, active, strong fellow, who prefers to take introductions slow and cautiously. He is hoping to find a forever home in a quieter, low dog-trafficked, neighborhood with experienced adopters. Wonder loves his own people very much and isn't too keen on sharing them with others, so he is hoping to find a special someone or two someones with whom to wander through the days ahead. Why not wander down to meet Wonder today!"
),
Dog(
44373538,
"Fuzzy",
"Terrier Mix",
"https://dl5zpyw5k3jeb.cloudfront.net/photos/pets/44373538/1/?bust=1554262696&width=1080",
"Fuzzy is a male Terrier mix and he's about a whole 8 weeks hold, which means plenty of mischief and fun trying to explore the world around him. And that means he should be finding his new forever home really soon so that he'll have fun getting to know people, places, toys, and maybe even other fur kids like him.\n" +
"\nDon't wait, these puppies don't last long..."
),
Dog(
44371030,
"Happy",
"Golden Retriever",
"https://thehappypuppysite.com/wp-content/uploads/2017/12/puppy2.jpg",
"What's not to love about a Golden Retriever!"
)
)

fun getDog(dogId: Long) = Observable.fromCallable {
Thread.sleep(2000)
dogs.find { it.id == dogId }
}

fun getDogs(): Observable<List<Dog>> = Observable.fromCallable<List<Dog>> {
Thread.sleep(2000)
dogs
}.subscribeOn(Schedulers.io())

fun adoptDog(dog: Dog) = Single.just(dog)
Expand Down
32 changes: 28 additions & 4 deletions sample-dogs/src/main/res/layout-v21/dog_detail_fragment.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,30 @@
android:layout_height="match_parent"
android:background="@color/colorPrimary">

<androidx.core.widget.ContentLoadingProgressBar
android:id="@+id/progress_bar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/error"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:textSize="24sp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="An error will be shown here"
tools:visibility="visible" />

<com.airbnb.mvrx.dogs.views.DogImageView
android:id="@+id/image"
android:layout_width="0dp"
Expand Down Expand Up @@ -60,11 +84,11 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@{dog.breeds}"
android:textColor="@android:color/white"
android:textSize="24sp"
app:layout_constraintStart_toStartOf="@id/nameView"
app:layout_constraintTop_toBottomOf="@id/nameView"
android:text="@{dog.breeds}"
tools:text="Terrier, Pit Bull Mix" />

<TextView
Expand All @@ -74,9 +98,9 @@
android:layout_marginStart="16dp"

android:layout_marginTop="16dp"
android:text="@{dog.name}"
android:textColor="@android:color/white"
android:textSize="32sp"
android:text="@{dog.name}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/image"
tools:text="Clover" />
Expand All @@ -91,12 +115,12 @@
android:background="@drawable/adopt_button_background"
android:elevation="8dp"
android:gravity="center"
android:onClick="@{() -> handler.onLoveClicked()}"
android:text="@string/love_dog"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:onClick="@{() -> handler.onLoveClicked()}" />
app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>