Good Morning brothers. I am working on an android form in Koltin which will save the data into MySQL. The problem I am facing is how can I save calculated data to an EditText field while entering data. I tried to add the calculation in oCreate instance but the intent crashes cause there is null point Exception as the form created is empty values. My code is appended below. Any help will be appreciated. Thanks.
I am trying to calculate value of project cost * ITRation / 100 and set the value to editTextITAMount but I am unable to do so.
class ProjectActivity : AppCompatActivity() {
//edittext and spinner
private var editTextProjectName: EditText? = null
private var spinnerProjectType: Spinner? = null
private var editTextDepartment: EditText? = null
private var editTextDateAwarded: EditText? = null
private var editTextProjectLocation: EditText? = null
private var editTextProjectCity: EditText? = null
private var editTextProjectDistrict: EditText? = null
private var spinnerJointVenture: Spinner? = null
private var editTextJointVentureCoy: EditText? = null
private var spinnerProjectStatus: Spinner? = null
private var editTextProjectCost: EditText? = null
private var spinnerITRatio: Spinner? = null
private var editTextITAmount: EditText? = null
private var spinnerGSTBST: Spinner? = null
private var editTextGSTBSTAmount: EditText? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_project)
//getting it from xml
editTextProjectName = findViewById(R.id.editTextProjectName) as EditText
spinnerProjectType = findViewById(R.id.spinnerProjectType) as Spinner
editTextDepartment = findViewById(R.id.editTextDepartment) as EditText
val mPickTimeBtn = findViewById<ImageButton>(R.id.imageButton)
editTextDateAwarded = findViewById(R.id.editTextDateAwarded) as EditText
editTextProjectLocation = findViewById(R.id.editTextProjectLocation) as EditText
editTextProjectCity = findViewById(R.id.editTextProjectCity) as EditText
editTextProjectDistrict = findViewById(R.id.editTextProjectDistrict) as EditText
spinnerJointVenture = findViewById(R.id.spinnerJointVenture) as Spinner
editTextJointVentureCoy = findViewById(R.id.editTextJointVentureCoy) as EditText
spinnerProjectStatus = findViewById(R.id.spinnerProjectStatus) as Spinner
editTextProjectCost = findViewById(R.id.editTextProjectCost) as EditText
spinnerITRatio = findViewById(R.id.spinnerITRatio) as Spinner
editTextITAmount = findViewById(R.id.editTextITAmount) as EditText
spinnerGSTBST = findViewById(R.id.spinnerGSTBST) as Spinner
editTextGSTBSTAmount = findViewById(R.id.editTextGSBSTAmount) as EditText
val c = Calendar.getInstance()
val year = c.get(Calendar.YEAR)
val month = c.get(Calendar.MONTH)
val day = c.get(Calendar.DAY_OF_MONTH)
mPickTimeBtn.setOnClickListener {
val dpd = DatePickerDialog(this, DatePickerDialog.OnDateSetListener { view, year, monthOfYear, dayOfMonth ->
// Display Selected date in TextView
editTextDateAwarded!!.setText("" + dayOfMonth + "/" + month + "/" + year)
}, year, month, day)
dpd.show()
}
//adding a click listener to button
this.findViewById<Button>(R.id.buttonAddProject).setOnClickListener { addProject() }
//in the second button click
//opening the activity to display all the artist
//it will give error as we dont have this activity so remove this part for now to run the app
}
private fun calculation() {
}
//adding a new record to database
private fun addProject() {
//getting the record values
val projectName = editTextProjectName?.text.toString()
val projectType = spinnerProjectType?.selectedItem.toString()
val department = editTextDepartment?.text.toString()
val dateAwarded = editTextDateAwarded?.text.toString()
val projectLocation = editTextProjectLocation?.text.toString()
val projectCity = editTextProjectCity?.text.toString()
val projectDistrict = editTextProjectDistrict?.text.toString()
val jointVenture = spinnerJointVenture?.selectedItem.toString()
val jointVentureWith = editTextJointVentureCoy?.text.toString()
val projectStatus = spinnerProjectStatus?.selectedItem.toString()
val projectCost= editTextProjectCost?.text.toString()
val ITRatio = spinnerITRatio?.selectedItem.toString()
val ITAmount= editTextITAmount?.text.toString()
val GSTBST = spinnerGSTBST?.selectedItem.toString()
val GSTBSTAmount= editTextGSTBSTAmount?.text.toString()
val a: Int = findViewById<TextView>(R.id.editTextProjectCost).getText().toString().toInt()
val b: Int = findViewById<Spinner>(R.id.spinnerITRatio).getSelectedItem().toString().toInt()
val multiplication = a * b / 100
editTextITAmount!!.setText("" + multiplication)
//creating volley string request
val stringRequest = object : StringRequest(
Request.Method.POST, EndPoints.URL_ADD_PROJECT,
Response.Listener<String> { response ->
try {
val obj = JSONObject(response)
Toast.makeText(applicationContext, obj.getString("message"), Toast.LENGTH_LONG)
.show()
val intent = Intent(applicationContext, ProjectsViewActivity::class.java)
startActivity(intent)
} catch (e: JSONException) {
e.printStackTrace()
}
},
object : Response.ErrorListener {
override fun onErrorResponse(volleyError: VolleyError) {
Toast.makeText(applicationContext, volleyError.message, Toast.LENGTH_LONG)
.show()
}
}) {
#Throws(AuthFailureError::class)
override fun getParams(): Map<String, String> {
val params = HashMap<String, String>()
params.put("projectName", projectName)
params.put("projectType", projectType)
params.put("department", department)
params.put("dateAwarded", dateAwarded)
params.put("projectLocation", projectLocation)
params.put("projectCity", projectCity)
params.put("projectDistrict", projectDistrict)
params.put("jointVenture", jointVenture)
params.put("jointVentureWith", jointVentureWith)
params.put("projectStatus", projectStatus)
params.put("projectCost", projectCost)
params.put("ITRatio", ITRatio)
params.put("ITAmount", ITAmount)
params.put("GSTBST", GSTBST)
params.put("GSTBSTAmount", GSTBSTAmount)
return params
}
}
//adding request to queue
VolleySingleton.instance?.addToRequestQueue(stringRequest)
}
}
Related
On Button Click, I want to get data on second activity from edit text only if the Switch button is ON but unable to do this anyone can help me to resolve this issue. Thanks
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val nextButton = findViewById<Button>(R.id.nextButton)
nextButton.setOnClickListener {
nextPage()
}
}
private fun nextPage(){
val etName = findViewById<EditText>(R.id.name)
val etEmail = findViewById<EditText>(R.id.email)
val etPhone = findViewById<EditText>(R.id.phone)
val etPassPort = findViewById<CheckBox>(R.id.checkbox)
var passport = ""
if (etPassPort.isChecked) { passport = etPassPort.text.toString() }
val mName = etName.text.toString()
val mEmail = etEmail.text.toString()
val mPhone = etPhone.text.toString()
val intent = Intent(this#MainActivity, ViewActivity::class.java)
intent.putExtra("Name", mName)
intent.putExtra("Email", mEmail)
intent.putExtra("Phone", mPhone)
intent.putExtra("CHECKBOX", passport)
val mySwitch = findViewById<SwitchCompat>(R.id.mySwitch)
mySwitch.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
val et = findViewById<EditText>(R.id.sponsorName)
val mEt = et.text.toString()
intent.putExtra("SPONSOR", mEt)
}
}
startActivity(intent)
}
}
SecondActivity.kt
class ViewActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_view)
val intent = intent
val mName = intent.getStringExtra("Name")
val mEmail = intent.getStringExtra("Email")
val mPhone = intent.getStringExtra("Phone")
val checkbox = intent.getStringExtra("CHECKBOX")
val mEt = intent.getStringExtra("SPONSOR")
//textview
val resultTv = findViewById<View>(R.id.resultTV) as TextView
//setText
resultTv.text = mName+"\n"+mEmail+"\n"+mPhone+"\n"+checkbox+"\n"+mEt
}
}
Switch button code is working fine when i release it from the Button Click. Under the Button Click only null value is showing in Output.
I resolved the issue of Switch Button by declaring it globally here is my working code.
MainActivity.kt
class MainActivity : AppCompatActivity() {
var sponsor : Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val mySwitch = findViewById<SwitchCompat>(R.id.mySwitch)
mySwitch.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
sponsor = true
}
}
val nextButton = findViewById<Button>(R.id.nextButton)
nextButton.setOnClickListener {
nextPage()
}
}
private fun nextPage(){
val etName = findViewById<EditText>(R.id.name)
val etEmail = findViewById<EditText>(R.id.email)
val etPhone = findViewById<EditText>(R.id.phone)
val etPassPort = findViewById<CheckBox>(R.id.checkbox)
var passport = ""
if (etPassPort.isChecked) { passport = etPassPort.text.toString() }
val mName = etName.text.toString()
val mEmail = etEmail.text.toString()
val mPhone = etPhone.text.toString()
val intent = Intent(this#MainActivity, ViewActivity::class.java)
val et = findViewById<EditText>(R.id.sponsorName)
val mEt = et.text.toString()
intent.putExtra("SPONSOR", mEt)
intent.putExtra("Name", mName)
intent.putExtra("Email", mEmail)
intent.putExtra("Phone", mPhone)
intent.putExtra("CHECKBOX", passport)
intent.putExtra("Switch",sponsor.toString())
startActivity(intent)}}
SecondActivity.kt
class ViewActivity : AppCompatActivity() {
private lateinit var pdfButton: Button
private var permissionCode = 101
private val STORAGE_CODE: Int = 100
val resultTv = findViewById<View>(R.id.resultTV) as TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_view)
val intent = intent
val mName = intent.getStringExtra("Name")
val mEmail = intent.getStringExtra("Email")
val mPhone = intent.getStringExtra("Phone")
val checkbox = intent.getStringExtra("CHECKBOX")
val mEt = intent.getStringExtra("SPONSOR")
val sponsor1 = intent.getStringExtra("Switch")
//textview
//setText
resultTv.text =
mName + "\n" + mEmail + "\n" + mPhone + "\n" + checkbox + "\n" + mEt + "\n" + sponsor1
if (sponsor1 == "true") {
resultTv.text = mName + "\n" + mEmail + "\n" + mPhone + "\n" + checkbox + "\n" + mEt
} else {
resultTv.text = mName + "\n" + mEmail + "\n" + mPhone + "\n" + checkbox
}
I know where is the problem, first of all you call the buttonCLick, and inside it you call the method nextPage(), if we look closely, this block of code
val mySwitch = findViewById<SwitchCompat>(R.id.mySwitch)
mySwitch.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
val et = findViewById<EditText>(R.id.sponsorName)
val mEt = et.text.toString()
intent.putExtra("SPONSOR", mEt)
}
}
is inside your click button, and by default your switch is not checked, so you pass all data, but intent.putExtra("SPONSOR", mEt) is not executed, so when the second activity receive the data is show a null error because val mEt = intent.getStringExtra("SPONSOR") is null.
You have two solution, either you write the block of the switch code outside the click button, or in the second activity you check with a conditionif all your data are not null.
I have created an app for my college project, it's an app to get the product quantity and store in data base.
The problem is when I decrement it goes below 0(-1,-2....) so i want to set the range, min 0 when i decrement and max 10 when i increment it.
Screenshot
this is my code..
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as ViewHolder).bind(cartItems[position])
holder.itemView.decrement_in_cart.setOnClickListener {
val databaseHelper = DatabaseHelper(it.context)
val item_name = holder.itemView.cart_item_name.text.toString()
val count = holder.itemView.cart_item_count.text.toString().toInt()
val count_new = databaseHelper.increase_decrease_in_cart("decrement", item_name, count)
holder.itemView.cart_item_count.text = count_new.toString()
}
holder.itemView.increment_in_cart.setOnClickListener {
val databaseHelper = DatabaseHelper(it.context)
val item_name = holder.itemView.cart_item_name.text.toString()
val count = holder.itemView.cart_item_count.text.toString().toInt()
val count_new = databaseHelper.increase_decrease_in_cart("increment", item_name, count)
holder.itemView.cart_item_count.text = count_new.toString()
}
holder.itemView.remove_from_cart.setOnClickListener {
val databaseHelper = DatabaseHelper(it.context)
val item_name = holder.itemView.cart_item_name.text.toString()
databaseHelper.delete_from_cart(item_name)
val cartFirebase = Cart_Firebase()
cartFirebase.updateCart()
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as ViewHolder).bind(cartItems[position])
holder.itemView.decrement_in_cart.setOnClickListener {
val databaseHelper = DatabaseHelper(it.context)
val item_name = holder.itemView.cart_item_name.text.toString()
val count = itemCountCheck(holder.itemView.cart_item_count.text.toString().toInt())
val count_new = databaseHelper.increase_decrease_in_cart("decrement", item_name, count)
holder.itemView.cart_item_count.text = count_new.toString()
}
holder.itemView.increment_in_cart.setOnClickListener {
val databaseHelper = DatabaseHelper(it.context)
val item_name = holder.itemView.cart_item_name.text.toString()
val count = itemCountCheck(holder.itemView.cart_item_count.text.toString().toInt())
val count_new = databaseHelper.increase_decrease_in_cart("increment", item_name, count)
holder.itemView.cart_item_count.text = count_new.toString()
}
holder.itemView.remove_from_cart.setOnClickListener {
val databaseHelper = DatabaseHelper(it.context)
val item_name = holder.itemView.cart_item_name.text.toString()
databaseHelper.delete_from_cart(item_name)
val cartFirebase = Cart_Firebase()
cartFirebase.updateCart()
}
}
private fun itemCountCheck(value: Int):Int {
if(value < 0){
return 0
}else if(value > 10){
return 10
}else{
return value
}
}
You can achieve this by writing a minimal function.
val count = itemCountCheck(holder.itemView.cart_item_count.text.toString().toInt())
val count_new = databaseHelper.increase_decrease_in_cart("decrement", item_name, count)
holder.itemView.cart_item_count.text = count_new.toString()
You're
reading the current item_count
passing it to a function in databaseHelper and storing the result
setting that result as the new item_count in the display
so you should probably handle your bounding logic in databaseHelper, since that's the thing that's doing validation, computing a new count and telling you what it is.
(Really databaseHelper should hold the current count internally, and you just call "increment" or "decrement" with the item name, so it can update and give you a new value to display. You shouldn't need to read the display to tell it what's currently in the cart, y'know? This way is open to bugs and security issues)
I am using a custom adapter to display a list of contacts on AutoTextComplete but when I try to run it I get the error "kotlin.Unit cannot be cast to java.util.List" for
mContact = filterResults.values **as List<Contact>**
Contact is a Serializable object and is how i am retrieving contact names as objects in the List - code is below... I have tried looking for a solution elsewhere, but have not been able to resolve... if you can redirect or solution or guide will be amazing thanks
private var invoice: Invoice? = null
private lateinit var contact: Contact
private var invoiceItems: List<InvoiceItems>? = null
private lateinit var contactSelect: ArrayList<Contact>
private lateinit var dueDate: Calendar
private val calendar = Calendar.getInstance()
private var total = 0
private var subTotal = 0
private var taxrate = 0
private var invoiceType: String = ""
private var invoiceUpdt: InvoiceItems? = null
private var j: String? = null
private var clientLkey: String? = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_edit_invoice)
val toolbar: Toolbar = findViewById(R.id.toolbar_editinv)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayShowHomeEnabled(true)
val invoiceClient = findViewById<AutoCompleteTextView>(R.id.invoiceClient)
val invoiceDueDt = findViewById<TextView>(R.id.invoiceDueDt)
dueDate = Calendar.getInstance()
//getting values from intent
invoice = intent.getSerializableExtra("invoice") as? Invoice
invoiceItems = intent.getSerializableExtra("invoiceItem") as? List<InvoiceItems>
invoiceUpdt = intent.getSerializableExtra("invoiceItemUpdt") as? InvoiceItems
j = intent.getStringExtra("i")
if (invoice == null){
invoiceType = "new"
supportActionBar?.title = "Add Invoice"
addinvoiceItem()
} else {
editInvoice()
}
//Setup Due date for the invoice
invoiceDueDt.setOnClickListener {
showCalendar()
}
//Auto complete based on database for selecting the client
val clientContact: List<Contact> = ArrayList<Contact>()
val adapter = ClientSelectAdapter(this, R.layout.userlatomcontacts, clientContact)
invoiceClient.setAdapter(adapter)
invoiceClient.threshold = 2
invoiceClient.setOnItemClickListener { parent, _, position, id ->
val selectedClient = parent.adapter.getItem(position) as Contact?
invoiceClient.setText(selectedClient?.name)
clientLkey = selectedClient?.lookupKey
}
}
inner class ClientSelectAdapter(
context: Context,
#LayoutRes private val layoutResource: Int,
private var allContacts: List<Contact>
):
ArrayAdapter<Contact>(context, layoutResource, allContacts),
Filterable {private var mContact: List<Contact> = allContacts
override fun getCount(): Int {
return mContact.size
}
override fun getItem(p0: Int): Contact {
return mContact[p0]
}
override fun getItemId(p0: Int): Long {
// Or just return p0
return mContact[p0].id.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
var view = convertView
if (view == null) {
view = LayoutInflater.from(parent.context)
.inflate(layoutResource, parent, false)
}
val invoiceClient = view!!.findViewById<View>(R.id.invoiceClient) as TextView
invoiceClient.text = mContact[position].name
val clientProfile = view.findViewById<View>(R.id.profile_image) as ShapeableImageView
Picasso.get().load(mContact[position].photoUri)
.placeholder(R.drawable.ic_baseline_whatshot_24).fit().centerCrop()
.into(clientProfile)
return view
}
override fun getFilter(): Filter {
return object : Filter() {
override fun publishResults(
charSequence: CharSequence?,
filterResults: FilterResults
) {
**mContact = filterResults.values as List<Contact>**
notifyDataSetChanged()
}
override fun performFiltering(charSequence: CharSequence?): FilterResults {
val queryString = charSequence?.toString()?.toLowerCase(Locale.ROOT)
val results = FilterResults()
results.values = if (queryString == null || queryString.isEmpty())
allContacts
else {
val db = AppDatabase.getDatabase(context)
allContacts = db.contactsDao().getBySearch(queryString)
}
return results
}
}
}
}
According to kotlin documentations Branches of if branches can be blocks. In this case, the last expression is the value of a block
So, in your case, when code enters the else block, the last expression is assignment, and assignments return Unit in kotlin. You may check this situation with this simple example:
var temp = 0
var result: Int = if (temp > 0) {
5
} else {
temp = 5
}
You would see the ide error at temp = 5 since it returns Unit whereas result expects Int.
To sum up, you just need to change your else block as follows:
else {
val db = AppDatabase.getDatabase(context)
allContacts = db.contactsDao().getBySearch(queryString)
allContacts
}
I just make a recyclerview and the data is doubled with this logic :
if(itemsList != null)
{
while (itemsList.hasNext()) {
val inFormat: DateFormat = SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS'Z'")
val outFormat: DateFormat = SimpleDateFormat("MM/dd/yyyy hh:mm")
val inFormatTwo: DateFormat = SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'")
val outFormatTwo: DateFormat = SimpleDateFormat("MM/dd/yyyy hh:mm")
val detail = itemsList.iterator().next().listIterator()
while(detail.hasNext())
{
val item = detail.next()
val status = item.status
val type = item.itemType
val pickupPoint = item.pickupPoint
val name = item.requesterDetails.elementAt(0).name
val reqDate = item.requestDate
val pickupTime = item.pickupTime
val reviewDate = item.pickupTime
val purpose = item.rejectReason
val quantity = item.quantity
val isActive = item.isActive
val isLatest = item.isLatest
var itemList : Any
val reqDateFormatted : Date?
val reqDateFix : String
reqDateFormatted = inFormat.parse(reqDate)
reqDateFix = outFormat.format(reqDateFormatted!!)
var pickupTimeFormatted : Date?
var pickupTimeFix = ""
if(pickupTime.length == 24)
{
pickupTimeFormatted = inFormat.parse(pickupTime)
pickupTimeFix = outFormat.format(pickupTimeFormatted)
} else if(pickupTime.length == 20)
{
pickupTimeFormatted = inFormatTwo.parse(pickupTime)
pickupTimeFix = outFormatTwo.format(pickupTimeFormatted!!)
}
if(isLatest == "Y")
{
itemList = DataModel(
type + " Request",
status,
name,
type,
quantity.toString(),
reqDateFix,
reviewDate,
pickupPoint,
pickupTimeFix,
purpose,
isActive,
isLatest
)
itemsData.add(itemList)
adapter.notifyDataSetChanged()
}
}
}
}
Basically, it is used to inform the user of the item they request, so the data comes from API. So, if itemsList is not null then while itemsList array has elements and inside it also exists array(s) and inside the array, I add each string to ArrayList and then isLatest string is equal to Y then add those arrays to itemList as a DataModel and then save them by adding itemList to itemsData. What makes the array doubled, thank you for your help
Notify the changes to adapter after the while loop and not after each add.
Try this:
if(itemsList != null)
{
while (itemsList.hasNext()) {
val inFormat: DateFormat = SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS'Z'")
val outFormat: DateFormat = SimpleDateFormat("MM/dd/yyyy hh:mm")
val inFormatTwo: DateFormat = SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'")
val outFormatTwo: DateFormat = SimpleDateFormat("MM/dd/yyyy hh:mm")
val detail = itemsList.iterator().next().listIterator()
while(detail.hasNext())
{
val item = detail.next()
val status = item.status
val type = item.itemType
val pickupPoint = item.pickupPoint
val name = item.requesterDetails.elementAt(0).name
val reqDate = item.requestDate
val pickupTime = item.pickupTime
val reviewDate = item.pickupTime
val purpose = item.rejectReason
val quantity = item.quantity
val isActive = item.isActive
val isLatest = item.isLatest
var itemList : Any
val reqDateFormatted : Date?
val reqDateFix : String
reqDateFormatted = inFormat.parse(reqDate)
reqDateFix = outFormat.format(reqDateFormatted!!)
var pickupTimeFormatted : Date?
var pickupTimeFix = ""
if(pickupTime.length == 24)
{
pickupTimeFormatted = inFormat.parse(pickupTime)
pickupTimeFix = outFormat.format(pickupTimeFormatted)
} else if(pickupTime.length == 20)
{
pickupTimeFormatted = inFormatTwo.parse(pickupTime)
pickupTimeFix = outFormatTwo.format(pickupTimeFormatted!!)
}
if(isLatest == "Y")
{
itemList = DataModel(
type + " Request",
status,
name,
type,
quantity.toString(),
reqDateFix,
reviewDate,
pickupPoint,
pickupTimeFix,
purpose,
isActive,
isLatest
)
itemsData.add(itemList)
}
}
}
adapter.notifyDataSetChanged()
}
I need to download images from AWS S3 and update ImageViews inside a recycler view. I am using ViewModel for downloading files from S3. A file object is observing inside onBindViewHolder() method and once receive the file my intention was to update the image belongs with that particular holder.
But the problem is if there were two rows, then two images need to download. So each view holder will attach with the observer. After downloading the first file, both the image views inside the recycler view become updated with the first image and after downloading the second image, both images updated with the second image. I am a little bit confuse about working. Please help me with this.
I cannot use Glide for this. Because S3 have authentication. So, I need to use S3 library for downloading files.
override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
val postUrl = listData[position].postUrl
val createdAt = listData[position].createdAt
val postImage = listData[position].postImage
val postVideo = listData[position].postVideo
val postVideoThumbnail = listData[position].postVideoThumbnail
val groupId = listData[position].groupId
val postStatus = listData[position].postStatus
val postId = listData[position].postId
val userId = listData[position].userId
val postHeading = listData[position].postHeading
val postDescription = listData[position].postDescription
val updatedAt = listData[position].updatedAt
val profileName = listData[position].userName
val profileImage = listData[position].profileImage
val likeCount = listData[position].likeCount
val commentCount = listData[position].commentCount
var key = ""
if(!profileImage.isNullOrEmpty()){
Glide.with(activity).load(profileImage) to holder.imgProfile
}
holder.textName.text = profileName.substring(0, 1).toUpperCase() + profileName.substring(1).toLowerCase()
holder.textPostedDateTime.text = SimpleDateFormat(POST_LIST_DATE_FORMAT).format(Date(createdAt))
holder.textPostHeading.text = postHeading
if(postDescription.isNullOrEmpty() || postDescription == "null"){
holder.textPostDescription.visibility = View.GONE
} else{
holder.textPostDescription.visibility = View.VISIBLE
holder.textPostDescription.text = postDescription
}
if(postUrl.isNullOrEmpty() || postUrl == "null"){
holder.textPostLink.visibility = View.GONE
} else{
holder.textPostLink.visibility = View.VISIBLE
holder.textPostLink.text = postUrl
}
if(postVideoThumbnail.isNullOrEmpty() || postVideoThumbnail == "null"){
holder.imgPostVideoPreview.visibility = View.GONE
} else{
holder.imgPostVideoPreview.visibility = View.VISIBLE
loadImageToFile(holder.imgPostVideoPreview, postVideoThumbnail, position)
key = postVideoThumbnail
}
if(postImage.isNullOrEmpty() || postImage == "null"){
holder.imgPostImagePreview.visibility = View.GONE
} else{
holder.imgPostImagePreview.visibility = View.VISIBLE
loadImageToFile(holder.imgPostImagePreview, postImage, position)
key = postImage
}
holder.textLikeCount.text = likeCount.toString()
holder.textCommentCount.text = commentCount.toString()
if(!isSelfPosts){
holder.layoutCommentLikeShare.visibility = View.VISIBLE
holder.imgAddComment.setOnClickListener { }
holder.imgAddLike.setOnClickListener { }
holder.imgShare.setOnClickListener { }
}
holder.itemView.setOnClickListener {
moveTOPostDetails(postId, listData[position], Environment.getExternalStorageDirectory().path + "/" + EXTERNAL_STORAGE_FOLDER_NAME + "/" + key.substring(key.lastIndexOf("/")+1))
}
}
class ListViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val imgProfile: ImageView = itemView.imgProfile
val textName: TextView = itemView.textName
val textPostedDateTime: TextView = itemView.textPostedDateTime
val textPostHeading: TextView = itemView.textPostHeading
val textPostDescription: TextView = itemView.textPostDescription
val textPostLink: TextView = itemView.textPostLink
val imgPostVideoPreview: ImageView = itemView.imgPostVideoPreview
val imgPostImagePreview: ImageView = itemView.imgPostImagePreview
val textCommentCount: TextView = itemView.textCommentCount
val textLikeCount: TextView = itemView.textLikeCount
val layoutCommentLikeShare: LinearLayout = itemView.layoutCommentLikeShare
val imgAddComment: ImageView = itemView.imgAddComment
val imgAddLike: ImageView = itemView.imgAddLike
val imgShare: ImageView = itemView.imgShare
}
private fun moveTOPostDetails(postId: String, fetchPostsResponseModel: FetchPostsResponseModel, imageFileName: String){
val intent = Intent(activity, PostDetails::class.java)
intent.putExtra("POST_DETAILS", fetchPostsResponseModel)
intent.putExtra("IS_SELF_POST", isSelfPosts)
intent.putExtra("IMAGE_FILE_NAME", imageFileName)
activity.startActivity(intent)
}
private fun loadImageToFile(imageView: ImageView, key: String, position: Int){
var postListAdapterViewModel: PostListAdapterViewModel = ViewModelProviders.of(fragment).get(PostListAdapterViewModel::class.java)
postListAdapterViewModel.init(activity)
postListAdapterViewModel.getMediaFile()?.observe(fragment, Observer<File>{ file ->
var a=position
imageView.setImageURI(Uri.fromFile(file))
} )
postListAdapterViewModel.performDownload(key)
}
This is my viewmodel
class PostListAdapterViewModel(application: Application):AndroidViewModel(application){
private val file = MutableLiveData<File>()
private lateinit var context: Context
fun init(context: Context) {
this.context = context
AWSMobileClient.getInstance().initialize(context).execute()
}
fun performDownload(key : String){
val credentials = BasicAWSCredentials(AMAZON_S3_ACCESS_KEY, AMAZON_S3_SECRET_KEY)
val s3Client = AmazonS3Client(credentials)
val transferUtility = TransferUtility.builder()
.context(context)
.awsConfiguration(AWSMobileClient.getInstance().configuration)
.s3Client(s3Client)
.build()
val downloadObserver = transferUtility.download (
key,
File(Environment.getExternalStorageDirectory().path + "/" + EXTERNAL_STORAGE_FOLDER_NAME + "/" + key.substring(key.lastIndexOf("/")+1)))
// Attach a listener to get state updates
downloadObserver.setTransferListener(object : TransferListener {
override fun onStateChanged(id: Int, state: TransferState) {
if (state == TransferState.COMPLETED) {
// Handle a completed upload.
file.value = File(Environment.getExternalStorageDirectory().path + "/" + EXTERNAL_STORAGE_FOLDER_NAME + "/" + key.substring(key.lastIndexOf("/")+1))
}
}
override fun onProgressChanged(id: Int, current: Long, total: Long) {
try {
val done = (((current.toDouble() / total) * 100.0).toInt()) //as Int
Log.d("PostListAdapterVM", "DOWNLOAD - - ID: $id, percent done = $done")
}
catch (e: Exception) {
Log.e("PostListAdapterVM", "Trouble calculating progress percent", e)
}
}
override fun onError(id: Int, ex: Exception) {
Log.d("PostListAdapterVM", "DOWNLOAD ERROR - - ID: $id - - EX: ${ex.message.toString()}")
}
})
// If you prefer to poll for the data, instead of attaching a
// listener, check for the state and progress in the observer.
if (downloadObserver.state == TransferState.COMPLETED) {
// Handle a completed upload.
}
Log.d("PostListAdapterVM", "Bytes Transferrred: ${downloadObserver.bytesTransferred}")
}
fun getMediaFile(): MutableLiveData<File> {
return file
}
}