#android #kotlin #spinner #viewmodel #android-spinner
#Android #kotlin #счетчик #viewmodel #android-счетчик
Вопрос:
Я пытаюсь реализовать корзину редактирования в своем проекте. Для этого я использовал счетчик. Я опубликовал два метода: один с использованием ViewModel и один без. Когда я не использую ViewModel, он работает нормально. Проблема заключается в использовании ViewModel.
Без использования ViewModel он отправляет правильное значение в вызове, правильно устанавливая значение в счетчике при повторном посещении корзины, однако при использовании ViewModel, если я устанавливаю счетчик как 3, он показывает успех, но при повторном просмотре я вижу 8 в счетчике и даже в запросе REST, который я делаюиспользуя Postman, я вижу 8 в ответе.
Адаптер:
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 OnItemClick {
fun DeleteItem(position: Int, id:Int)
fun EditItem(position: Int,id: Int)
}
Активность:
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>
Приведенный выше код работает без реализации ViewModel.Он редактируется и получил успешный ответ
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)
}
}
}
})
}
}
Активность:
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()
}
}
}
}
}
Из реализации ViewModel я получаю ответ об успешном завершении в toast, означающий, что корзина была успешно обновлена, но когда я снова возвращаюсь к корзине, я вижу значение как 8 в счетчике.
Например, если я установлю счетчик как 3, он покажет успех (корзина успешно обновлена), но когда я возвращаюсь, я вижу 8 в счетчике.
Мне нужна помощь в правильном кодировании счетчика, чтобы он принимал правильное значение элемента, который я выбрал в счетчике при повторном просмотре.
Комментарии:
1. Если вы можете сделать так, чтобы ваш
OnItemClick
отображал элемент, а не позицию идентификатор, я думаю, вы можете упростить проблему. Я думаюviewModel.country[position]=country[position]
, что это нарушает ваш код.2. @EpicPandaForce если я отлажу эту строку
viewModel.country[position]=country[position]
и установлю счетчик как 3 …. отладчик показывает, что позиция равна 2, а идентификатор равен 14 …. это означает, что я получаю правильное положение счетчика, но он неправильно настроен и отправляет количество счетчиков в вызове3. Если я сравниваю вызовы API из обеих реализаций, я вижу, что с реализацией ViewModel вы называете это:
RetrofitClient.instance.editCart(token, id.toInt(), country)
где country — это весь массив, а из предыдущей реализации я вижу это:RetrofitClient.instance.editCart(token, id, arrayOf(country[position]))
. Может ли это быть возможной проблемой?4. я так думаю … вот почему он всегда отправляет значение как 8 …???? но как мне получить позицию в viewmodel?? @JeelVankhede
5. Разве вы не можете передать его в методе в качестве параметра, подобного
position: Int
?