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

Converted Recipes adapter in Binding Adpater setting directly from XM… #22

Open
wants to merge 1 commit into
base: master
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ android {
}
buildFeatures{
viewBinding = true
dataBinding = true
}

buildTypes {
debug {
debuggable true
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/java/com/task/data/DataRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ class DataRepository @Inject constructor(private val remoteRepository: RemoteDat
}.flowOn(ioDispatcher)
}

override suspend fun requestRecipes2(): Flow<Recipes> {
return flow {
emit(remoteRepository.requestRecipes2())
}.flowOn(ioDispatcher)
}


override suspend fun doLogin(loginRequest: LoginRequest): Flow<Resource<LoginResponse>> {
return flow {
emit(localRepository.doLogin(loginRequest))
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/task/data/DataRepositorySource.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import kotlinx.coroutines.flow.Flow

interface DataRepositorySource {
suspend fun requestRecipes(): Flow<Resource<Recipes>>
suspend fun requestRecipes2(): Flow<Recipes>

suspend fun doLogin(loginRequest: LoginRequest): Flow<Resource<LoginResponse>>
suspend fun addToFavourite(id: String): Flow<Resource<Boolean>>
suspend fun removeFromFavourite(id: String): Flow<Resource<Boolean>>
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/com/task/data/remote/RemoteData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@ constructor(private val serviceGenerator: ServiceGenerator, private val networkC
}
}

override suspend fun requestRecipes2(): Recipes {
val recipesService = serviceGenerator.createService(RecipesService::class.java)
return when (val response = processCall(recipesService::fetchRecipes)) {
is List<*> -> {
Recipes(response as ArrayList<RecipesItem>)
}
else -> {
//response as Int
Recipes(response as ArrayList<RecipesItem>)

}
}
}

private suspend fun processCall(responseCall: suspend () -> Response<*>): Any? {
if (!networkConnectivity.isConnected()) {
return NO_INTERNET_CONNECTION
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/com/task/data/remote/RemoteDataSource.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ import com.task.data.dto.recipes.Recipes

internal interface RemoteDataSource {
suspend fun requestRecipes(): Resource<Recipes>
suspend fun requestRecipes2(): Recipes
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import android.view.View.GONE
import android.view.View.VISIBLE
import android.widget.SearchView
import android.widget.SearchView.OnQueryTextListener
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.LiveData
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.snackbar.Snackbar
Expand Down Expand Up @@ -39,25 +40,24 @@ class RecipesListActivity : BaseActivity() {

@Inject
lateinit var viewModelFactory: ViewModelFactory
private lateinit var recipesAdapter: RecipesAdapter

override fun initViewBinding() {
binding = HomeActivityBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)

binding = DataBindingUtil.setContentView(this,R.layout.home_activity)
binding.lifecycleOwner= this

}

override fun initializeViewModel() {
recipesListViewModel = viewModelFactory.create(RecipesListViewModel::class.java)
binding.vm = recipesListViewModel
binding.vm?.getRecipes()
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportActionBar?.title = getString(R.string.recipe)
val layoutManager = LinearLayoutManager(this)
binding.rvRecipesList.layoutManager = layoutManager
binding.rvRecipesList.setHasFixedSize(true)
recipesListViewModel.getRecipes()

}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
Expand Down Expand Up @@ -97,16 +97,6 @@ class RecipesListActivity : BaseActivity() {
}


private fun bindListData(recipes: Recipes) {
if (!(recipes.recipesList.isNullOrEmpty())) {
recipesAdapter = RecipesAdapter(recipesListViewModel, recipes.recipesList)
binding.rvRecipesList.adapter = recipesAdapter
showDataView(true)
} else {
showDataView(false)
}
}

private fun navigateToDetailsScreen(navigateEvent: SingleEvent<RecipesItem>) {
navigateEvent.getContentIfNotHandled()?.let {
val nextScreenIntent = Intent(this, DetailsActivity::class.java).apply {
Expand Down Expand Up @@ -154,7 +144,10 @@ class RecipesListActivity : BaseActivity() {
private fun handleRecipesList(status: Resource<Recipes>) {
when (status) {
is Resource.Loading -> showLoadingView()
is Resource.Success -> status.data?.let { bindListData(recipes = it) }
is Resource.Success -> status.data?.let {
// bindListData(recipes = it)
// recipesListViewModel.recipesLiveData.value = it
}
is Resource.DataError -> {
showDataView(false)
status.errorCode?.let { recipesListViewModel.showToastMessage(it) }
Expand All @@ -163,7 +156,6 @@ class RecipesListActivity : BaseActivity() {
}

override fun observeViewModel() {
observe(recipesListViewModel.recipesLiveData, ::handleRecipesList)
observe(recipesListViewModel.recipeSearchFound, ::showSearchResult)
observe(recipesListViewModel.noSearchFound, ::noSearchResult)
observeEvent(recipesListViewModel.openRecipeDetails, ::navigateToDetailsScreen)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,14 @@ constructor(private val dataRepositoryRepository: DataRepositorySource) : BaseVi
val recipesLiveDataPrivate = MutableLiveData<Resource<Recipes>>()
val recipesLiveData: LiveData<Resource<Recipes>> get() = recipesLiveDataPrivate

// @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
// val recipesLiveDataPrivate2 = MutableLiveData<Resource<Recipes>>()
// val recipesLiveData2: MutableLiveData<Resource<Recipes>> get() = recipesLiveDataPrivate2


private val _loading: MutableLiveData<Boolean> =
MutableLiveData(true).apply { value = true }
val loading: MutableLiveData<Boolean> get() = _loading
//TODO check to make them as one Resource
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
val recipeSearchFoundPrivate: MutableLiveData<RecipesItem> = MutableLiveData()
Expand Down Expand Up @@ -64,9 +71,30 @@ constructor(private val dataRepositoryRepository: DataRepositorySource) : BaseVi
recipesLiveDataPrivate.value = Resource.Loading()
wrapEspressoIdlingResource {
dataRepositoryRepository.requestRecipes().collect {
recipesLiveDataPrivate.value = it
when(it!!){
is Resource.Loading -> _loading.value = true
is Resource.Success -> {
_loading.value = false
it?.let {
recipesLiveDataPrivate.value = it

}
}
is Resource.DataError ->{

_loading.value = false
it.errorCode?.let {
showToastMessage(it)
}
}
}




}
}

}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.task.ui.component.recipes.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.task.data.dto.recipes.Recipes
import com.task.data.dto.recipes.RecipesItem
import com.task.databinding.RecipeItemBinding
import com.task.ui.base.listeners.RecyclerItemListener
Expand All @@ -12,7 +13,7 @@ import com.task.ui.component.recipes.RecipesListViewModel
* Created by AhmedEltaher
*/

class RecipesAdapter(private val recipesListViewModel: RecipesListViewModel, private val recipes: List<RecipesItem>) : RecyclerView.Adapter<RecipeViewHolder>() {
class RecipesAdapter(private val recipesListViewModel: RecipesListViewModel, var recipes: Recipes?) : RecyclerView.Adapter<RecipeViewHolder>() {

private val onItemClickListener: RecyclerItemListener = object : RecyclerItemListener {
override fun onItemSelected(recipe: RecipesItem) {
Expand All @@ -26,11 +27,13 @@ class RecipesAdapter(private val recipesListViewModel: RecipesListViewModel, pri
}

override fun onBindViewHolder(holder: RecipeViewHolder, position: Int) {
holder.bind(recipes[position], onItemClickListener)
holder.bind(recipes!!.recipesList[position], onItemClickListener)
}

override fun getItemCount(): Int {
return recipes.size
if (recipes != null)
return recipes?.recipesList!!.size
else return 0;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.task.ui.component.recipes.adapter

import android.util.Log
import android.view.View
import androidx.databinding.BindingAdapter
import androidx.recyclerview.widget.RecyclerView
import com.task.data.dto.recipes.Recipes
import com.task.data.dto.recipes.RecipesItem
import com.task.ui.component.recipes.RecipesListViewModel


@BindingAdapter(value = ["recipes", "viewModel"])
fun setRepositories(view: RecyclerView, recipes: Recipes?, vm: RecipesListViewModel) {

view.adapter?.run {
if (this is RecipesAdapter) {
this.recipes = recipes
this.notifyDataSetChanged()
}
} ?: run {
RecipesAdapter(vm,recipes).apply { view.adapter = this }
}
}

@BindingAdapter("android:loader")
fun View.toVisble(visibility: Boolean) {
if (visibility) {
this.visibility = View.VISIBLE
} else {
this.visibility = View.GONE

}
}
94 changes: 54 additions & 40 deletions app/src/main/res/layout/home_activity.xml
Original file line number Diff line number Diff line change
@@ -1,47 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
xmlns:tools="http://schemas.android.com/tools">

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_recipes_list"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<FrameLayout
android:id="@+id/pb_loading"
<data>
<variable
name="vm"
type="com.task.ui.component.recipes.RecipesListViewModel" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:visibility="gone"
tools:visibility="visible">
android:layout_height="match_parent">


<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_recipes_list"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:viewModel="@{vm}"
app:recipes="@{vm.recipesLiveData.data}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toTopOf="parent" />

<ProgressBar
style="?android:attr/progressBarStyleLarge"
<FrameLayout
android:id="@+id/pb_loading"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:loader="@{vm.loading}"
android:visibility="gone"
tools:visibility="visible">

<ProgressBar
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:indeterminate="true" />
</FrameLayout>

<TextView
android:id="@+id/tv_no_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:indeterminate="true" />
</FrameLayout>

<TextView
android:id="@+id/tv_no_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/no_data"
android:textColor="@android:color/holo_red_dark"
android:textSize="@dimen/font_32x"
android:textStyle="italic|bold"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
android:text="@string/no_data"
android:textColor="@android:color/holo_red_dark"
android:textSize="@dimen/font_32x"
android:textStyle="italic|bold"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
8 changes: 3 additions & 5 deletions local.properties
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file should *NOT* be checked into Version Control Systems,
## This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
sdk.dir=/Users/amohamed/Library/Android/sdk
#Wed Sep 30 10:43:52 PKT 2020
sdk.dir=C\:\\Users\\Jaman\\AppData\\Local\\Android\\Sdk