Annon
Annon

Reputation: 843

How to cache data on Android using Jetpack Compose

Let's say I've 3 screens,

  1. HomeScreen, which contains list of users
  2. UserProfileScreen, which contains user details and their posts
  3. PostDetailScreen, which contains details about post
@Composable
fun HomeScreen() {
    LazyColumn {
        // Show user profiles
    }
}
@Composable
fun UserProfileScreen(
    userId: Long,
    userProfileViewModel: UserProfileViewModel
) {
    LaunchedEffect(Unit) {
        userProfileViewModel.getProfileAndPosts(userId)
    }
    
    UserProfileView()
    LazyColumn {
        // Show posts
    }
}
@Composable
fun PostDetailScreen(
    postId: Long,
    postViewModel: PostViewModel
) {
    LaunchedEffect(Unit) {
        postViewModel.getPost(postId)
    }

    PostView()
}

When I move from HomeScreen to UserProfileScreen, I use LaunchedEffect(Unit) {} to fetch user profile and posts from network. And if I click on any post, it will navigate to PostDetailScreen and display post details.

Now, If I come back to UserProfileScreen (via backpress), it will re-fetch the user data because getProfileAndPosts() is a function and accept userId so (I guess) can't be cached to viewModelScope (If it were variable without any parameter, we can cache it)

How do I avoid that? Instagram seems to does exactly that. It does not re-fetch data. Though, they're on XML view, but it should not make any difference.

Upvotes: 2

Views: 3290

Answers (1)

Vahid Garousi
Vahid Garousi

Reputation: 715

If I understand your problem correctly

You must use ViewModel. And define a data class with this name:

data class UserProfileState(
val wereThePostsReceived : Boolean = false,
val posts : List<Post> = emptyList()
)

And change its value to true after successfully receiving the posts in ViewModel.

fun getProfileAndPosts(userId : String) {
  viewModelScope.launch {
    val result = getPostsUseCase(userId)
      when(result) {
        is Succuss -> {
          state = state.copy(
             wereThePostsReceived = true,
            posts = // your interactor , usecase result
          )
        is Failed -> {
     }
  }
}

Then use it in the Compose layout as follows:

  LaunchedEffect(wereThePostsReceived) {
  if(wereThePostsReceived == false){
        postViewModel.getProfileAndPosts(postId)
   }
  }

Upvotes: 3

Related Questions