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()
}
Related
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)
}
}
How can I stop creating a quoteData variable every time in my view model?
This solution is working, but the amount of repetitive code is terrifying
class QuoteDetailsViewModel(application: Application) : AndroidViewModel(application) {
private val quoteRepository: QuoteRepository = QuoteRepository(application)
private val quoteId = MutableLiveData<String>("")
val quoteAuthor = MutableLiveData<String>("")
val quoteContent = MutableLiveData<String>("")
val quoteDescription = MutableLiveData<String>("")
val quoteLastUpdate = MutableLiveData<String>("")
val onSaveClickEvent = MutableLiveData<ViewModelEvent<Unit>>()
val onCancelClickEvent = MutableLiveData<ViewModelEvent<Unit>>()
val onDeleteClickEvent = MutableLiveData<ViewModelEvent<String?>>()
var isNewQuote = false
fun setInitialData(arguments: Bundle?) {
if (arguments != null) {
val quoteData = arguments.getSerializable(KEY_DATA) as Quote
isNewQuote = false
quoteData.let { quote ->
quoteId.postValue(quote.id)
quoteAuthor.postValue(quote.author)
quoteContent.postValue(quote.quote)
quoteDescription.postValue(quote.description)
quoteLastUpdate.postValue(quote.lastUpdated.getFormattedDate())
}
} else {
isNewQuote = true
}
}
fun onViewClick(viewId: Int) {
val currentTime = Calendar.getInstance().time
when (viewId) {
R.id.actionSave -> {
if (!isNewQuote) {
val quoteData = Quote(
id = this.quoteId.value ?: "",
author = this.quoteAuthor.value ?: "",
quote = this.quoteContent.value ?: "",
description = this.quoteDescription.value ?: "",
lastUpdated = currentTime
)
quoteRepository.update(quoteData)
} else {
val quoteData = Quote(
id = UUID.randomUUID().toString(),
author = this.quoteAuthor.value ?: "",
quote = this.quoteContent.value ?: "",
description = this.quoteDescription.value ?: "",
lastUpdated = currentTime
)
quoteRepository.insert(quoteData)
}
onSaveClickEvent.postValue(ViewModelEvent(Unit))
}
R.id.actionCancel -> onCancelClickEvent.postValue(ViewModelEvent(Unit))
R.id.actionDelete -> onDeleteClickEvent.postValue(ViewModelEvent(this.quoteId.value))
}
}
fun onDeleteItemResult(guid: String?) {
val currentTime = Calendar.getInstance().time
val quoteData = Quote(
id = guid ?: "",
author = this.quoteAuthor.value ?: "",
quote = this.quoteContent.value ?: "",
description = this.quoteDescription.value ?: "",
lastUpdated = currentTime
)
quoteRepository.delete(quoteData)
}
companion object {
fun newBundle(quote: Quote?): Bundle {
return Bundle().apply {
putSerializable(KEY_DATA, quote)
}
}
}
}
Also here is code of my Quote:
#Entity(tableName = "quotes")
class Quote(
#PrimaryKey
val id: String,
val author: String,
val quote: String,
val description: String,
#ColumnInfo(name = "last_updated")
val lastUpdated: Date?
) : Serializable
And here is the code when I click on a list item
val allQuotes: LiveData<List<Quote>>
init {
allQuotes = quoteRepository.allQuotes
}
fun onListItemClick(itemIndex: Int) {
onListItemClickEvent.postValue(
ViewModelEvent(QuoteDetailsViewModel.newBundle(allQuotes.value?.getOrNull(itemIndex)))
)
}
Then I get to my view model - QuoteDetailsViewModel
Problem: 1. The x-axis values are not mapped with the group of the bars why?
I have managed to show all the bar data by setting xAxis.axisMaximum = 50f but it is displaying a lot of "0" xAxis labels in the graph so how can i solve this?
Here's the code:
private fun populateCharts(chartData: List<ResponseGetPenetrationGrowth>){
try {
val prev_year = ArrayList<BarEntry>()
val current_year = ArrayList<BarEntry>()
val xAxis_label = ArrayList<String>()
var i = 0f
val currentYear = Calendar.getInstance().get(Calendar.YEAR)
for (item in chartData!!) {
xAxis_label.add(item.brand)
prev_year.add(BarEntry(i,item.prevYear.toFloat()))
current_year.add(BarEntry(i,item.currentYear.toFloat()))
i++
}
val prevDataSet = BarDataSet(prev_year,(currentYear-1).toString())
prevDataSet.setColors(ContextCompat.getColor(penetration_chart.context, R.color.prev_year_bar))
val currentDataSet = BarDataSet(current_year, currentYear.toString())
currentDataSet.setColors(ContextCompat.getColor(penetration_chart.context, R.color.current_year_bar))
val barData = BarData(prevDataSet, currentDataSet)
penetration_chart.data = barData
val xAxis = penetration_chart.getXAxis()
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM)
xAxis.valueFormatter = IAxisValueFormatter { value, axis ->
if (value.toInt()> 0 && (value.toInt() < xAxis_label.size)) {
xAxis_label.get(value.toInt())
} else {
"0"
}
}
xAxis.setCenterAxisLabels(true)
val barSpace = 0.06f
val groupSpace = 0.8f
xAxis.axisMinimum = 0f
xAxis.axisMaximum = 50f
// val yAxisLeft = penetration_chart.axisLeft
// yAxisLeft.axisMinimum = 0f
// val yAxisRight = penetration_chart.axisRight
// yAxisRight.axisMinimum = 0f
penetration_chart.setDrawGridBackground(false)
val description = Description()
description.text = ""
penetration_chart.description = description
barData.setBarWidth(0.5f)
penetration_chart.groupBars(0f, groupSpace, barSpace)
penetration_chart.getAxisRight().setDrawGridLines(false);
penetration_chart.getAxisLeft().setDrawGridLines(false);
penetration_chart.getXAxis().setDrawGridLines(false);
penetration_chart.setVisibleXRangeMaximum(5f)
penetration_chart.invalidate()
}catch (e: Exception){
e.printStackTrace()
}
}
Please help.
This worked like charm, few tweakings:
private fun populateCharts(chartData: List<ResponseGetPenetrationGrowth>){
try {
val prev_year = ArrayList<BarEntry>()
val current_year = ArrayList<BarEntry>()
val xAxis_label = ArrayList<String>()
var i = 0f
val currentYear = Calendar.getInstance().get(Calendar.YEAR)
xAxis_label.add("")
for (item in chartData!!) {
xAxis_label.add(item.brand)
prev_year.add(BarEntry(i,item.prevYear.toFloat()))
current_year.add(BarEntry(i,item.currentYear.toFloat()))
i++
}
xAxis_label.add("")
val prevDataSet = BarDataSet(prev_year,(currentYear-1).toString())
prevDataSet.setColors(ContextCompat.getColor(penetration_chart.context, R.color.prev_year_bar))
prevDataSet.valueTextSize = 8f
val currentDataSet = BarDataSet(current_year, currentYear.toString())
currentDataSet.valueTextSize = 8f
currentDataSet.setColors(ContextCompat.getColor(penetration_chart.context, R.color.current_year_bar))
val barData = BarData(prevDataSet, currentDataSet)
penetration_chart.data = barData
barData.setBarWidth(0.3f)
val xAxis = penetration_chart.getXAxis()
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM)
xAxis.valueFormatter = IndexAxisValueFormatter(xAxis_label)
xAxis.granularity= 1f
xAxis.setCenterAxisLabels(true)
val barSpace = 0.05f
val groupSpace = 0.3f
xAxis.axisMinimum = 1f
xAxis.axisMaximum = xAxis_label.size - 1.1f
penetration_chart.setDrawGridBackground(false)
val description = Description()
description.text = ""
penetration_chart.description = description
penetration_chart.groupBars(1f, groupSpace, barSpace)
penetration_chart.getAxisRight().setDrawGridLines(false);
penetration_chart.getAxisLeft().setDrawGridLines(false);
penetration_chart.getXAxis().setDrawGridLines(false);
val legend = penetration_chart.legend
legend.position = Legend.LegendPosition.BELOW_CHART_CENTER
penetration_chart.extraBottomOffset = 20f
penetration_chart.setVisibleXRangeMaximum(5f)
penetration_chart.invalidate()
}catch (e: Exception){
e.printStackTrace()
}
}
Now i am writing my small molar mass calculator and i can't fix one bug. In MainActivity.kt i fill array from my .xml file, after that i use Regex to parse user input. BUT if i type, for example "C" (carbon) in my program it doesn't recognize it. WHY?
MainActivity.kt:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val adapter = MoleculeAdapter(this)
moleculeView.layoutManager = LinearLayoutManager(this)
moleculeView.setHasFixedSize(true)
moleculeView.adapter = adapter
val parser = resources.getXml(R.xml.elements)
val elements = Array(127) { Element() }
thread {
var i = 0
while (parser.eventType != END_DOCUMENT) {
if (parser.eventType == START_TAG && parser.name == "element") {
elements[i].number = parser.getAttributeIntValue(null, "number", 0)
elements[i].letter = parser.getAttributeValue(null, "letter")
elements[i].name = parser.getAttributeValue(null, "name")
val weight = parser.getAttributeValue(null, "weight")
elements[i].weight = if (weight.isNotEmpty()) weight.toFloat() else 0F
i++
}
parser.next()
}
parser.close()
}.join()
Log.i("elements:", elements.joinToString { it.toString() + "\n" })
val lowerCaseLetters = "abcdefghiklmnopqrstuy"
val elementsRegex = Regex("""[ABCDEFGHIKLMNOPRSTUVWXYZ]([$lowerCaseLetters]{2}|[$lowerCaseLetters]?)\d*""")
val digitsRegex = Regex("""\d+""")
formulaInput.doOnTextChanged { text, _, _, _ ->
lateinit var foundedElements: List<Element>
thread {
foundedElements = elementsRegex
.findAll(text ?: "")
.map {
elements.find { element ->
Log.i("value", it.value + " " + it.value)
if (it.value.filter { it.isLetter() } == element.letter) {
val number = digitsRegex.find(it.value)
if (number != null) {
try {
element.moleculeCount = number.value.toInt()
element.weight = element.weight * number.value.toInt()
} catch (e: NumberFormatException) { }
}
element.percentage = adapter.getTotalWeight(element.weight) * 100
true
} else false
}
}.filterNotNull().toList()
}.join()
adapter.insertElements(foundedElements)
}
}
}
Element.kt:
data class Element(var number: Int = -1,
var letter: String = "",
var name: String = "",
var weight: Float = 0F,
var percentage: Float = 100F,
var moleculeCount: Int = 1)
xml file item example:
<element
number="6"
letter="С"
name="Углерод"
weight="12.011" />
I can't believe it, in my xml file letter "С" was a cyrillic letter "C" (\u0421)! And because of this equals check "С" == "C" was failing.
Huge Thanks to Wiktor Stribiżew for his comment.
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
}
}