Retrofit call inside an adapter in android
Asked Answered
C

2

1

I'm performing a retrofit call inside an adapter..i have successfully implemented and also it is giving me the desired output but is it a good practice to perform this under adapter?????

my app is --> product selling app-->in my cart-->im displaying the product list which user wants to buy-->for this required an adapter-->there im performing a swipe to delete function -->performing retrofit call on delete(holder.delete.setonclicklistener {...}) button

my code is-->

        holder.tvDelete.setOnClickListener(View.OnClickListener { view ->
        progressDialog.show()

        val token: String = SharedPrefManager.getInstance(context).user.access_token.toString()
        RetrofitClient.instance.deletecart(token, id.toString())
            .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
                    progressDialog.dismiss()
                    (context as Activity).finish()

                    if (res.body()?.status == 200) {
                        Toast.makeText(
                            context,
                            res.body()?.message,
                            Toast.LENGTH_LONG
                        ).show()
                        progress()

                        mItemManger.removeShownLayouts(holder.swipelayout)
                        notifyItemChanged(position)
                        notifyItemRemoved(position)
                        dataList?.removeAt(position)
                        notifyItemRangeChanged(position, dataList?.size!!)
                        mItemManger.closeAllItems()


                    } else {
                        try {
                            val jObjError =
                                JSONObject(response.errorBody()!!.string())
                            Toast.makeText(
                                context,
                                jObjError.getString("message") + jObjError.getString("user_msg"),
                                Toast.LENGTH_LONG
                            ).show()
                        } catch (e: Exception) {
                            Toast.makeText(context, e.message, Toast.LENGTH_LONG).show()
                            Log.e("errorrr", e.message)
                        }
                    }
                }
            })

        mItemManger.bindView(holder.itemView, position)

    })

the above code is working

i have also gone through this --> passing data from on click function of my recycler adaptor

this link i performed but in activity i wont be getting access to this code in activity

    mItemManger.removeShownLayouts(holder.swipelayout)
                        notifyItemChanged(position)
                        notifyItemRemoved(position)
                        dataList?.removeAt(position)
                        notifyItemRangeChanged(position, dataList?.size!!)
                        mItemManger.closeAllItems()

need clarification on this

need help thanks

Edit:-- i followed the above link here is my code

interface

interface OnItemClick {
fun onItemClicked(position: Int)

 }

activity

class AddToCart:BaseClassActivity(), OnItemClick{
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.add_to_cart)
    getWindow().setExitTransition(null)
    getWindow().setEnterTransition(null)
    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)))


    adapter.notifyDataSetChanged()
     adapter.setItemClick(this)
    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 onItemClicked(position: Int) {

    val token: String = SharedPrefManager.getInstance(applicationContext).user.access_token.toString()
    RetrofitClient.instance.deletecart(token, id.toString())
        .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
                (applicationContext as Activity).finish()

                if (res.body()?.status == 200) {
                    Toast.makeText(
                        applicationContext,
                        res.body()?.message,
                        Toast.LENGTH_LONG
                    ).show()
                    val intent =
                        Intent(applicationContext, AddToCart::class.java)
                    intent.flags =
                        Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK
                    applicationContext.startActivity(intent)
                    (applicationContext as Activity?)!!.overridePendingTransition(0, 0)


                } 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)
                    }
                }
            }
        })

}
   }

adapter:--

class CartAdapter(private val context: Context, private val dataList: MutableList<DataCart?>?) :
RecyclerSwipeAdapter<CartAdapter.CustomViewHolder>() , AdapterView.OnItemSelectedListener{ //added RecyclerSwipeAdapter and override
private var itemClick: OnItemClick? = null

inner class CustomViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
    View.OnClickListener {
    val mView: View
  val swipelayout:SwipeLayout
    val productiamge: ImageView
    val productname: TextView
    val productcategory: TextView
    val productprice: TextView
    val tvDelete:TextView
    val spin:Spinner
    init {
        mView = itemView
    productiamge= mView.findViewById(R.id.imagecart)
       productname= mView.findViewById(R.id.imagenamecart)
        productcategory= mView.findViewById(R.id.imagecategory)

     productprice =mView.findViewById(R.id.price)
        swipelayout=mView.findViewById(R.id.swipe)
        tvDelete=mView.findViewById(R.id.tvDelete)
         spin = mView.findViewById(R.id.spinner) as Spinner
        tvDelete.setClickable(true);
        tvDelete.setOnClickListener(this);

    }

    override fun onClick(v: View?) {
        if (itemClick != null) {
            itemClick!!.onItemClicked(getPosition());
        }
    }


}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomViewHolder {
    val layoutInflater = LayoutInflater.from(parent.context)
    val view: View = layoutInflater.inflate(R.layout.addtocart_item, parent, false)

    return CustomViewHolder(view)
}

override fun getSwipeLayoutResourceId(position: Int): Int {
    return R.id.swipe;

}

override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
  val  progressDialog :ProgressDialog= ProgressDialog(context);
    holder.productname.text = dataList?.get(position)?.product?.name ?: null
    holder.productcategory.text = "(" +dataList?.get(position)?.product?.product_category +")"

    holder.productprice.text = dataList?.get(position)?.product?.cost.toString()

    Glide.with(context).load(dataList?.get(position)?.product?.product_images)
        .into(holder.productiamge)

    holder.swipelayout.setShowMode(SwipeLayout.ShowMode.PullOut)
    Log.e("checkidd", dataList?.get(position)?.product?.id.toString())
    // Drag From Right

    // Drag From Right
    holder.swipelayout.addDrag(
        SwipeLayout.DragEdge.Right,
        holder.swipelayout.findViewById(R.id.bottom_wrapper)
    )
     val id =dataList?.get(position)?.product?.id

    holder.tvDelete.setOnClickListener(View.OnClickListener { view ->
        mItemManger.removeShownLayouts(holder.swipelayout)
        notifyItemChanged(position)
        notifyItemRemoved(position)
        dataList?.removeAt(position)
        notifyItemRangeChanged(position, dataList?.size!!)
        mItemManger.closeAllItems()
    })
    mItemManger.bindView(holder.itemView, position)


}
    override fun getItemCount() = dataList?.size ?: 0

override fun onNothingSelected(p0: AdapterView<*>?) {
    TODO("Not yet implemented")
}

override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) {

}
fun getItemClick(): OnItemClick? {
    return itemClick
}

fun setItemClick(itemClick: OnItemClick?) {
    this.itemClick = itemClick
}

}

but im not getting an desired output help me

Cadell answered 23/10, 2020 at 6:51 Comment(10)
"is it a good practice to perform this under adapter??" - The theory says no because the adapter + viewholder only must be show the data and set the listeners, that´s all (UI module). The responsibility to implement the network logic is of a data network class, injecting your retrofit interface, and if you need another data from another datasource as SharedPreferences, your Repository could prepare the necessary data to do the call (Data Module). And if you need business logic and you want to implement a clean architecture, then you could to create a Domain Module (Use Cases + Entities)Tomblin
@ManuelMato can you see the edited codeCadell
One more step, and you'll move what you're doing into the ViewModel, that's what you are looking to accomplish :)Mississippian
@Mississippian that I got it viewmodel... But how do I pass the click of adapter? That delete button? And I can't get an instance of viewmodel in adapter? That I have to do it in activity ofcourse ?how do I access that holder.delete in activity... Really confused ☹️ Need helpCadell
You can technically pass the ViewModel to the Adapter, but I'd rather define an interface in the Adapter for the item click, then expose that to the Fragment, and the Fragment would call over to the VM.Mississippian
wow it worked @Mississippian thanks a lot..you always help me :) :)Cadell
@Mississippian need help in spinner selection using viewmodel --> #64538139Cadell
You should add the working code as an answerMississippian
@Mississippian okay i will do it :)Cadell
hi @Mississippian could u help me out here ->#76787465Cadell
C
2

with the help of user EpicPandaForce i got an answer to problem question

Interface::----

interface OnItemClick {
fun DeleteItem(position: Int, id:Int)
}

Adapter::----

    private var itemClick: OnItemClick? = null
     .
    .
     .
      holder.tvDelete.setOnClickListener(View.OnClickListener { view ->
        mItemManger.removeShownLayouts(holder.swipelayout)
        notifyItemChanged(position)
        notifyItemRemoved(position)
        dataList?.removeAt(position)
        itemClick?.DeleteItem(position,id!!.toInt())

        notifyItemRangeChanged(position, dataList?.size!!)
        mItemManger.closeAllItems()
    })
    mItemManger.bindView(holder.itemView, position)


    }
    .
    .
     .
     
fun setItemClick(itemClick: OnItemClick?) {
    this.itemClick = itemClick
}

Activity::----

class AddToCart:BaseClassActivity(), OnItemClick{
 .
 .
  .
   onCreate(){
            adapter.setItemClick(this);
       .
       .
       .
       }
         override fun DeleteItem(position: Int, id:Int) {
    progressDialog?.show()
        viewModel.product_id.value =id.toString()
    viewModel.loaddelete()
    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()
            }
        }
    }



}

Viewmodel::--------

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)
                    }
                }
            }
        })




}
Cadell answered 26/10, 2020 at 13:58 Comment(0)
B
0

This is not a good practice to make API calls in adapter. You can create callbacks from adapter to activity and should call this API code in activity itself. If you need some references from the adapter then you can create methods in adapter and call these methods in activity by creating adapter's object.

Bowling answered 23/10, 2020 at 7:0 Comment(8)
i have performed this --> https://mcmap.net/q/541404/-passing-data-from-on-click-function-of-my-recycler-adaptor but im not getting access of this code in my activity mItemManger.removeShownLayouts(holder.swipelayout) notifyItemChanged(position) notifyItemRemoved(position) dataList?.removeAt(position) notifyItemRangeChanged(position, dataList?.size!!) mItemManger.closeAllItems()Cadell
You need to move this code to adapter's method and call that method in class.Bowling
im getting error on this line adapter.setItemClick(this); red at setItemClickCadell
This will be populating error to, check what it is saying. I guess you have not implemented callback properly. or you can share your codeBowling
Let us continue this discussion in chat.Cadell
You need to add adapter.setItemClick(AddToCart.this)Bowling
Are you still facing issue? You need to give reference of class as you are in the recyclerview's listener.Bowling
can you come in discussion?Cadell

© 2022 - 2024 — McMap. All rights reserved.