Spinner value using retrofit and viewmodel
Asked Answered
A

0

3

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.

Alage answered 26/10, 2020 at 13:1 Comment(14)
If you can make it so that your OnItemClick exposes the item rather than position+id, I think you can simplify the issue. I think the viewModel.country[position]=country[position] is breaking your code, though.Putupon
@Putupon if i debugg this line viewModel.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 callAlage
If I compare API calls from both implementations, I see with ViewModel implementation you call this: RetrofitClient.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?Barbaraanne
i think so ...is that why it is always sending value as 8 ...???? but how do i get position in viewmodel?? @JeelVankhedeAlage
Can not you pass it in method as parameter like position: Int?Barbaraanne
you mean declared a like this viewmodel val position :Int?=-1 @JeelVankhede and then pass it to method RetrofitClient.instance.editCart(token, id, arrayOf(country[position])) ?Alage
Yeah, I'm still not able to figure out actual issue here but that's what I found out as a difference.Barbaraanne
im now getting error(crashing) as java.lang.ArrayIndexOutOfBoundsException: length=8; index=-1 @JeelVankhedeAlage
Let us continue this discussion in chat.Barbaraanne
Can you format the code better or give us the whole source code?Druid
@DragosRachieru i have included the relevant/important code only ...i think it irrelevant to put up all code....so still you want me to every code above like in place of commented section in question ????//Alage
The only way I could fix it is with 1.) complete code of this activity/viewmodel/adapter/layout and 2.) rewriting itPutupon
@Putupon i added full code of without implementation of viewmodelAlage
hey can you help here -->#66046772Isreal

© 2022 - 2024 — McMap. All rights reserved.