I tried to pass data from DetailActivity to PaymentActivity, but I got this error Here is the error and here is PaymentFragment after I comment textview that contain number format on it here it is. The user data pass successfully, but the product data unsuccess to pass I think. So how to pass the product data from DetailActivity to PaymentActivity
here is my code: Helpers File
object Helpers {
fun getDefaultGson(): Gson {
return GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.setDateFormat(Cons.DATE_FORMAT_SERVER)
.registerTypeAdapter(Date::class.java, JsonDeserializer { json, _, _ ->
val formatServer = SimpleDateFormat(Cons.DATE_FORMAT_SERVER, Locale.ENGLISH)
formatServer.timeZone = TimeZone.getTimeZone("UTC")
formatServer.parse(json.asString)
})
.registerTypeAdapter(Date::class.java, JsonSerializer<Date> { src, _, _ ->
val format = SimpleDateFormat(Cons.DATE_FORMAT_SERVER, Locale.ENGLISH)
format.timeZone = TimeZone.getTimeZone("UTC")
if (src != null) {
JsonPrimitive(format.format(src))
} else {
null
}
})
.create()
}
fun Throwable.getErrorBodyMessage(): String {
return if (this is HttpException) {
val errorCode = this.code()
if (errorCode == 405) {
"Method yang digunakan salah"
} else if (errorCode == 503) {
"Error Server"
} else {
val parseErrorBody = this.response()?.errorBody()!!.parseErrorBody()
if (parseErrorBody?.meta?.message == null) {
"Permintaan anda belum berhasil di proses. Silakan coba kembali"
} else {
parseErrorBody?.meta?.message.toString()
}
}
} else if (this is ConnectException || this is UnknownHostException) {
"Maaf Anda sedang Offline. Silakan coba kembali"
} else {
return if (this.message == null)
"Permintaan anda belum berhasil di proses. Silakan coba kembali"
else if (this.message.equals(""))
""
else
this.message!!
}
}
fun ResponseBody.parseErrorBody(): Wrapper<*>? {
val gson = Gson()
val adapter = gson.getAdapter(Wrapper::class.java)
try {
return adapter.fromJson(string())
} catch (e: IOException) {
e.printStackTrace()
}
return null
}
fun TextView.formatPrice(value: String) {
this.text = getCurrencyIdr(java.lang.Double.parseDouble(value))
}
fun getCurrencyIdr(price: Double): String {
val format = DecimalFormat("#,###,###")
return "Rp. " format.format(price).replace(",".toRegex(), ".")
}
fun Long.convertLongToTime(formatTanggal: String): String {
val date = Date(this)
val format = SimpleDateFormat(formatTanggal)
return format.format(date)
}
}
PaymentFragment: class PaymentFragment : Fragment(), PaymentContract.View {
var progressDialog: Dialog? = null
var total : Int = 0
lateinit var presenter: PaymentPresenter
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_payment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
(activity as DetailActivity?)!!.toolbarPayment()
var data = arguments?.getParcelable<Data>("data")
initView(data)
initView()
presenter = PaymentPresenter(this)
}
private fun initView(data: Data?) {
tvTitle.text = data?.name
tvPrice.formatPrice(data?.price.toString())
Glide.with(requireContext())
.load(data?.picturePath)
.into(tvPoster)
tvNameItem.text = data?.name
tvHarga.formatPrice(data?.price.toString())
if (!data?.price.toString().isNullOrEmpty()) {
var totalTax = data?.price?.div(10)
tvTax.formatPrice(totalTax.toString())
total = data?.price!! totalTax!! 50000
tvTotalPrice.formatPrice(total.toString())
} else {
tvPrice.text = "IDR. 0"
tvTax.text = "IDR. 0"
tvTotalPrice.text = "IDR. 0"
total = 0
}
var user = IcaCraft.getApp().getUser()
var userResponse = Gson().fromJson(user, User::class.java)
tvNameDeliver.text = userResponse?.name
tvPhoneDeliver.text = userResponse?.phoneNumber
tvAddressDeliver.text = userResponse?.address
tvHouseNo.text = userResponse?.houseNumber
tvCityDeliver.text = userResponse?.postalCode
btn_CheckoutNow.setOnClickListener {
presenter.getCheckout(
data?.id.toString(),
userResponse?.id.toString(),
"1",
total.toString(), it
)
}
}
private fun initView() {
progressDialog = Dialog(requireContext())
val dialogLayout = layoutInflater.inflate(R.layout.dialog_loader, null)
progressDialog?.let {
it.setContentView(dialogLayout)
it.setCancelable(false)
it.window?.setBackgroundDrawableResource(android.R.color.transparent)
}
}
override fun onCheckoutSuccess(checkoutResponse: CheckoutResponse, view: View) {
val i = Intent(Intent.ACTION_VIEW)
i.data = Uri.parse(checkoutResponse.paymentUrl)
startActivity(i)
Navigation.findNavController(view).navigate(R.id.action_fragmentPayment_to_fragmentPaymentSuccess)
}
override fun onCheckoutFailed(message: String) {
Toast.makeText(activity, message, Toast.LENGTH_LONG).show()
}
override fun showLoading() {
progressDialog?.show()
}
override fun dismissLoading() {
progressDialog?.dismiss()
}
}
DetailActivity:
class DetailFragment : Fragment() {
var data:Data?= null
var bundle:Bundle?= null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_detail, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
(activity as DetailActivity?)!!.toolbarDetail()
arguments?.let {
DetailFragmentArgs.fromBundle(it).data?.let {
initView(it)
}
}
btnOrderNow.setOnClickListener { view ->
Navigation.findNavController(view).navigate(R.id.action_fragmentDetail_to_fragmentPayment, bundle)
}
}
private fun initView(data: Data?) {
data?.let {
// bundle = bundleOf("data" to data)
Glide.with(requireContext())
.load(it.picturePath)
.into(ivPoster)
tvTitle.text = it.name
tvDescription.text = it.description
tvMaterials.text = it.materials
tvTotal.formatPrice(it.price.toString())
}
}
}
CodePudding user response:
I am not sure about the bug in the code but there are many other ways you can share data in between activities. Try using viewModel to share data between your activities. SharedPreferences are another way too. There are plenty of other ways but I think viewModel is the best way. I personally find it difficult to transfer data between fragments using arguments. So Good Luck!
CodePudding user response:
Your code is a bit complicated but the error is understandable. It says "You can not parse null to double". You define "price" as "Int?", so it can be "null" and when it is null, app crashes. This can be solved by doing the followings:
1- You can define your price "not null" and set a default value as 0.
@Expose
@SerializedName("price")
val price: Int = 0
2- If you do not want to change your data class, you need to control what to pass to "parseDouble()" method.
fun TextView.formatPrice(value: String) {
if (value != null) {
this.text = getCurrencyIdr(java.lang.Double.parseDouble(value))
} else {
this.text = getCurrencyIdr(0.0) // we didn't parse the null
}
}
If one of these individually will not solve your error try both, it has to solve it.