I'm trying to implement an editing cart in my project. For that, I have used a spinner. I posted two methods: one using ViewModel and one without. When I am not using ViewModel, it works fine. The problem is when using ViewModel.
Without using ViewModel, it posts the correct value in the call, setting the value properly in the spinner when I revisit the cart, however when using the ViewModel, if I set the spinner as 3, it shows success but upon revisiting I see 8 in the spinner and even in the REST request I make using Postman, I see 8 in the response.
Adapter:
var country = arrayOf(1, 2, 3, 4, 5, 6, 7, 8)
/*** */
val aa: ArrayAdapter <*> =
ArrayAdapter<Any?>(context, android.R.layout.simple_spinner_item, country)
aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
holder.spin.setAdapter(aa)
holder.spin.setSelection(dataList?.get(position)?.quantity!! - 1, false)
holder.spin.setOnItemSelectedListener(object : OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>,
view: View,
position1: Int,
id: Long
) {
progressDialog.show()
val id = dataList?.get(position)!!.product.id
itemClick?.EditItem(position1, id!!.toInt())
}
override fun onNothingSelected(parent: AdapterView<*>?) {
// todo for nothing selected
}
})
Interface:
interface OnItemClick {
fun DeleteItem(position: Int, id:Int)
fun EditItem(position: Int,id: Int)
}
Activity:
var country = arrayOf(1, 2, 3, 4, 5, 6, 7, 8)
/* */
override fun EditItem(position: Int, id: Int) {
val token: String = SharedPrefManager.getInstance(applicationContext).user.access_token.toString()
RetrofitClient.instance.editCart(token, id, arrayOf(country[position]))
.enqueue(object : Callback<DeleteResponse> {
override fun onFailure(call: Call<DeleteResponse>, t: Throwable) {
Log.d("res", "" + t)
}
override fun onResponse(call: Call<DeleteResponse>, response: Response<DeleteResponse>) {
progressDialog?.dismiss()
finish()
var res = response
if (res.isSuccessful) {
Toast.makeText(applicationContext, res.body()?.user_msg, Toast.LENGTH_LONG).show()
progressDialog?.dismiss()
val intent = Intent(applicationContext, AddToCart::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK
applicationContext.startActivity(intent)
overridePendingTransition(0, 0)
Log.d("kjsfgxhufb", response.body()?.user_msg.toString())
} else {
try {
val jObjError = JSONObject(response.errorBody()!!.string())
Toast.makeText(applicationContext, jObjError.getString("message") + jObjError.getString("user_msg"),
Toast.LENGTH_LONG).show()
} catch (e: Exception) {
Toast.makeText(applicationContext, e.message, Toast.LENGTH_LONG).show()
Log.e("errorrr", e.message)
}
}
}
})
}
API:
@FormUrlEncoded
@POST("editCart")
fun editCart(
@Header("access_token") token: String,
@Field("product_id") product_id: Int,
@Field("quantity") quantity: Array<Int>
): Call<DeleteResponse>
Above code is working without the implementation of ViewModel.It is getting edited and got success response
with ViewModel implementation
ViewModel:
class CartViewModel(context: Application, savedStateHandle: SavedStateHandle) :
AndroidViewModel(context) {
/// val product_id:String?=null
sealed class Result {
object Missing : Result()
object NetworkFailure : Result()
object Success : Result()
}
val product_id: MutableLiveData<String> = savedStateHandle.getLiveData("product_id", "")
var country =
arrayOf(1, 2, 3, 4, 5, 6, 7, 8)
private var Cart: MutableLiveData<CartResponse>? = null
val CartList: MutableLiveData<CartResponse>?
get() {
if (Cart == null) {
Cart = MutableLiveData<CartResponse>()
loadCartList()
}
return Cart
}
private val loginResultEmitter = EventEmitter<CartViewModel.Result>()
val Results: EventSource<CartViewModel.Result> = loginResultEmitter
private fun loadCartList() {
val token: String =
SharedPrefManager.getInstance(
getApplication()
).user.access_token.toString()
RetrofitClient.instance.listcart(token).enqueue(object :
Callback<CartResponse> {
override fun onFailure(call: Call<CartResponse>, t: Throwable) {
Toast.makeText(getApplication(), "falied", Toast.LENGTH_LONG).show()
}
override fun onResponse(
call: Call<CartResponse>,
response: Response<CartResponse>
) {
if (response.isSuccessful) {
Cart!!.value = response.body()
}
}
})
}
fun loaddelete() {
val id = product_id.value!!.toString().trim()
val token: String =
SharedPrefManager.getInstance(getApplication()).user.access_token.toString()
RetrofitClient.instance.deletecart(token, id)
.enqueue(object : Callback<DeleteResponse> {
override fun onFailure(call: Call<DeleteResponse>, t: Throwable) {
loginResultEmitter.emit(CartViewModel.Result.NetworkFailure)
Log.d("res", "" + t)
}
override fun onResponse(
call: Call<DeleteResponse>,
response: Response<DeleteResponse>
) {
var res = response
if (res.body()?.status == 200) {
Toast.makeText(
getApplication(),
res.body()?.message,
Toast.LENGTH_LONG
).show()
loginResultEmitter.emit(CartViewModel.Result.Success)
} else {
try {
val jObjError =
JSONObject(response.errorBody()!!.string())
Toast.makeText(
getApplication(),
jObjError.getString("message") + jObjError.getString("user_msg"),
Toast.LENGTH_LONG
).show()
} catch (e: Exception) {
Toast.makeText(getApplication(), e.message, Toast.LENGTH_LONG).show()
Log.e("errorrr", e.message)
}
}
}
})
}
fun loadEdit() {
val id = product_id.value!!.toString().trim()
val token: String =
SharedPrefManager.getInstance(getApplication()).user.access_token.toString()
RetrofitClient.instance.editCart(token, id.toInt(), country)
.enqueue(object : Callback<DeleteResponse> {
override fun onFailure(call: Call<DeleteResponse>, t: Throwable) {
Log.d("res", "" + t)
}
override fun onResponse(
call: Call<DeleteResponse>,
response: Response<DeleteResponse>
) {
var res = response
if (res.isSuccessful) {
Toast.makeText(getApplication(), res.body()?.user_msg, Toast.LENGTH_LONG)
.show()
} else {
try {
val jObjError = JSONObject(response.errorBody()!!.string())
Toast.makeText(getApplication(),
jObjError.getString("message") + jObjError.getString("user_msg"),
Toast.LENGTH_LONG
).show()
} catch (e: Exception) {
Toast.makeText(getApplication(), e.message, Toast.LENGTH_LONG).show()
Log.e("errorrr", e.message)
}
}
}
})
}
}
Activity:
class AddToCart : BaseClassActivity(), OnItemClick {
var progressDialog: ProgressDialog? = null
private val viewModel by viewModels<CartViewModel>()
var country =
arrayOf(1, 2, 3, 4, 5, 6, 7, 8)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.add_to_cart)
getWindow().setExitTransition(null)
getWindow().setEnterTransition(null)
val progressDialog: ProgressDialog = ProgressDialog(applicationContext);
var mActionBarToolbar = findViewById<androidx.appcompat.widget.Toolbar>(R.id.toolbartable);
setSupportActionBar(mActionBarToolbar);
// add back arrow to toolbar
setEnabledTitle()
mActionBarToolbar.setNavigationOnClickListener(View.OnClickListener {
onBackPressed()
})
placeorder.setOnClickListener {
val intent: Intent = Intent(applicationContext, AddressActivity::class.java)
startActivity(intent)
}
loadCart()
}
fun loadCart() {
val model = ViewModelProvider(this)[CartViewModel::class.java]
model.CartList?.observe(this, object : Observer<CartResponse> {
override fun onChanged(t: CartResponse?) {
generateDataList(t?.data?.toMutableList())
totalamount.setText(t?.total.toString())
}
})
}
fun generateDataList(dataList: MutableList<DataCart?>?) {
val recyclerView = findViewById<RecyclerView>(R.id.addtocartrecyleview) as? RecyclerView
val linear: LinearLayoutManager =
LinearLayoutManager(applicationContext, LinearLayoutManager.VERTICAL, false)
recyclerView?.layoutManager = linear
val adapter = CartAdapter(this@AddToCart, dataList)
recyclerView?.adapter = adapter
recyclerView?.addItemDecoration(DividerItemDecorator(resources.getDrawable(R.drawable.divider)))
// recyclerView?.setHasFixedSize(true)
adapter.setItemClick(this);
adapter.notifyDataSetChanged()
if (dataList?.isEmpty() ?: true) {
recyclerView?.setVisibility(View.GONE)
totalamount.setVisibility(View.GONE)
fl_footer.setVisibility(View.GONE)
placeorder.setVisibility(View.GONE)
emptytext.setVisibility(View.VISIBLE)
} else {
recyclerView?.setVisibility(View.VISIBLE)
totalamount.setVisibility(View.VISIBLE)
fl_footer.setVisibility(View.VISIBLE)
placeorder.setVisibility(View.VISIBLE)
emptytext.setVisibility(View.GONE)
}
recyclerView?.addOnScrollListener(object :
RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
Log.e("RecyclerView", "onScrollStateChanged")
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
}
})
}
override fun onBackPressed() {
super.onBackPressed()
val intent = Intent(this, HomeActivity::class.java)
startActivity(intent)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
android.R.id.home -> {
NavUtils.navigateUpFromSameTask(this)
true
}
else -> super.onOptionsItemSelected(item)
}
}
override fun onResume() {
super.onResume()
loadCart()
}
override fun DeleteItem(position: Int, id: Int) {
}
override fun EditItem(position: Int, id: Int) {
viewModel.product_id.value = id.toString()
viewModel.loadEdit()
viewModel.country[position] = country[position]
viewModel.Results.observe(this) { result ->
when (result) {
CartViewModel.Result.Missing -> {
Toast.makeText(
applicationContext, "product is missing", Toast.LENGTH_LONG
).show()
}
CartViewModel.Result.Success -> {
finish()
val intent = Intent(applicationContext, AddToCart::class.java)
intent.flags =
Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK
startActivity(intent)
overridePendingTransition(0, 0)
}
else -> {
Toast.makeText(applicationContext, "hello", Toast.LENGTH_LONG).show()
}
}
}
}
}
From the implementation of ViewModel, I am getting a success response in toast meaning that the cart has been successfully updated, but when I revisit the cart again I'm seeing the value as 8 in the spinner.
For example, if I set the spinner as 3 it shows success (cart updated successfully) but when I revisit I see 8 in the spinner.
I need help in coding the spinner correctly so that it takes the correct value of the item I selected in the spinner upon revisiting.
OnItemClick
exposes the item rather than position+id, I think you can simplify the issue. I think theviewModel.country[position]=country[position]
is breaking your code, though. – PutuponviewModel.country[position]=country[position]
and set spinner as 3 ....debugger shows position is 2 and id is 14 ....that means im getting a proper position of spinner but it is not setting properly and sending the spinner quantity in call – AlageRetrofitClient.instance.editCart(token, id.toInt(), country)
where country is entire array while from previous implementation, I see this:RetrofitClient.instance.editCart(token, id, arrayOf(country[position]))
. Can this be possible issue? – Barbaraanneposition: Int
? – Barbaraanne