RecyclerView.Adapter.onBindViewHolder()中的android viewmodel观察器更新每个项目

时间:2019-04-09 04:32:49

标签: android android-recyclerview android-viewholder android-viewmodel

我需要从AWS S3下载图像并更新回收者视图中的ImageViews。我正在使用ViewModel从S3下载文件。一个文件对象正在onBindViewHolder()方法内部进行观察,一旦接收到该文件,我的目的就是更新该特定所有者所拥有的图像。 但是问题是如果有两行,则需要下载两个图像。因此,每个视图持有者都将附加到观察者。在下载第一个文件之后,回收站视图内的两个图像视图都将使用第一个图像更新,而在下载第二个图像之后,两个图像都将使用第二个图像更新。我对工作有些困惑。请帮我解决一下这个。 我不能为此使用 Glide 。因为S3有身份验证。因此,我需要使用S3库下载文件。

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

这是我的视图模型

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
}

}

0 个答案:

没有答案