Я работаю над проектом приложения чата, где все работает нормально, но когда я пытаюсь отправить изображение, logcat показывает мне ошибку Адаптер не подключен; пропуская макет . В моем MessageChatactivity изображение, которое я храню в хранилище firebase, когда пользователь отправляет изображение, не извлекается из БД, но текстовые сообщения работают нормально. В базе данных, если это текстовое сообщение, я назначаю дочернему URL-адресу БД значение null, если это изображение, я назначаю то же самое с каталогом изображений, который я храню в хранилище Firebase.
заранее спасибо !!
MessageChatactivity:
package com.example.whatsapp
class MessageChatActivity : AppCompatActivity() {
// userIdVisit is the receiver user id
var userIdVisit: String=""
var firebaseUser: FirebaseUser? =null
var chatsAdapter: ChatsAdapter? = null
// Chat folder contains all the messages with the id stored in the DB.
var mChatList : List<Chat>? = null
private lateinit var recycler_view_chats: RecyclerView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_message_chat)
intent=intent
// to get both the sender id and the receiver id
// visit is defined in UserAdapter
userIdVisit = intent.getStringExtra("visit_id")
firebaseUser = FirebaseAuth.getInstance().currentUser
// to access the recycler view to put all the messages we stored in mChatList
recycler_view_chats = findViewById(R.id.recycler_view_chats)
recycler_view_chats.setHasFixedSize(true)
val linearLayoutManager = LinearLayoutManager(applicationContext)
linearLayoutManager.stackFromEnd = true
recycler_view_chats.layoutManager = linearLayoutManager
// to fetch the receiver name and profile pic
val reference = FirebaseDatabase.getInstance().reference
.child("Users").child(userIdVisit)
reference.addValueEventListener(object : ValueEventListener{
override fun onDataChange(p0: DataSnapshot)
{
// to get the dp of the receiver
val user : Users? = p0.getValue(Users::class.java)
username_mchat.text= user!!.getUserName()
Picasso.get().load(user.getProfile()).into(profile_image_mchat)
retrieveMessages(firebaseUser!!.uid,userIdVisit, user.getProfile())
}
override fun onCancelled(error: DatabaseError)
{
}
})
send_message_bt.setOnClickListener {
val message = text_message.text.toString()
if (message=="")
{
Toast.makeText(this@MessageChatActivity, "Please enter some message...", Toast.LENGTH_LONG).show()
}else
{
sendMessageToUser(firebaseUser!!.uid,userIdVisit,message)
}
// to make the text_message edittext null once we send a text
text_message.setText("")
}
attach_image_file_btn.setOnClickListener {
// to send the user to mobile phone gallery
val intent = Intent()
intent.action = Intent.ACTION_GET_CONTENT
intent.type = "image/*"
// to get the image from gallery
startActivityForResult(Intent.createChooser(intent,"Pick an image"),438)
}
}
private fun sendMessageToUser(senderId: String, receiverId: String?, message: String)
{
val reference = FirebaseDatabase.getInstance().reference
// have to create unique key for each message
val messageKey = reference.push().key
//to create a hash map
val messageHashMap = HashMap<String,Any?>()
messageHashMap["sender"] = senderId
messageHashMap["message"] = message
messageHashMap["receiver"] = receiverId
messageHashMap["isseen"] = false
messageHashMap["url"] = ""
messageHashMap["messageId"] = messageKey
// this creates a Chat folder in DB and places all the child of messageHashMap under it
reference.child("Chats")
.child(messageKey!!)
.setValue(messageHashMap)
.addOnCompleteListener { task ->
// to add the chats to Chats fragment for both sender and the receiver
if(task.isSuccessful)
{
// this is to retrieve the last message for each user (unread message)
// for sender add the receiver to his chat fragment
val chatListReference = FirebaseDatabase.getInstance()
.reference
.child("ChatList")
.child(firebaseUser!!.uid)
.child(userIdVisit)
chatListReference.addListenerForSingleValueEvent(object : ValueEventListener{
override fun onDataChange(p0: DataSnapshot) {
if (!p0.exists())
{
chatListReference.child("id").setValue(userIdVisit)
}
// for receiver add the sender to his chat fragment
val chatListReceiverRef = FirebaseDatabase.getInstance()
.reference
.child("ChatList")
.child(userIdVisit)
.child(firebaseUser!!.uid)
chatListReceiverRef.child("id").setValue(firebaseUser!!.uid)
}
override fun onCancelled(error: DatabaseError) {
}
})
// to implement the push notifications
val reference = FirebaseDatabase.getInstance().reference
.child("Users").child(firebaseUser!!.uid)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode==438 && resultCode == RESULT_OK && data!=null && data!!.data!=null)
{
// to display a loading bar
val progressBar = ProgressDialog(this)
progressBar.setMessage("sending image...")
progressBar.show()
val fileUri = data.data
// to send the image to a folder Chat Images in DB so that it can be send to the receiver
val storageReference = FirebaseStorage.getInstance().reference.child("Chat Images")
val ref = FirebaseDatabase.getInstance().reference
//unique id for each image like we did for text
val messageId = ref.push().key
val filePath = storageReference.child("$messageId.jpg")
var uploadTask : StorageTask<*>
uploadTask = filePath.putFile(fileUri!!)
uploadTask.continueWithTask(Continuation<UploadTask.TaskSnapshot,Task<Uri>> {task ->
// not
if (!task.isSuccessful)
{
task.exception?.let {
throw it
}
}
return@Continuation filePath.downloadUrl
}).addOnCompleteListener { task ->
if(task.isSuccessful)
{
val downloadUrl = task.result
val url = downloadUrl.toString()
val messageHashMap = HashMap<String,Any?>()
messageHashMap["sender"] = firebaseUser!!.uid
messageHashMap["message"] = "sent you an image."
messageHashMap["receiver"] = userIdVisit
messageHashMap["isseen"] = false
messageHashMap["url"] = url
messageHashMap["messageId"] = messageId
// all the above are Chats folder children in DB
ref.child("Chats").child(messageId!!).setValue(messageHashMap)
progressBar.dismiss()
// these info's are fetched using the Chat model class
}
}
}
}
private fun retrieveMessages(senderId: String, receiverId: String?, receiverImageUrl: String?)
{
// to store all the messages in mChatlist
mChatList = ArrayList()
// to retrieve all the messages under Chats folder in DB
val reference = FirebaseDatabase.getInstance().reference
.child("Chats")
reference.addValueEventListener(object : ValueEventListener{
override fun onDataChange(p0: DataSnapshot)
{
(mChatList as ArrayList<Chat>).clear()
for(snapshot in p0.children)
{
val chat = snapshot.getValue(Chat::class.java)
if (chat!!.getReceiver().equals(senderId) && chat.getSender().equals(receiverId)
|| chat.getReceiver().equals(receiverId) && chat.getSender().equals(senderId)
)
{
(mChatList as ArrayList<Chat>).add(chat)
}
chatsAdapter = ChatsAdapter(this@MessageChatActivity, (mChatList as ArrayList<Chat>), receiverImageUrl!!)
// after this we have to display the messages in the recycler view on activity_message_chat
recycler_view_chats.adapter = chatsAdapter
}
}
override fun onCancelled(p0: DatabaseError) {
}
})
}
}
это мой класс адаптера ChatsAdapter:
package com.example.whatsapp.AdapterClasses
class ChatsAdapter(
mContext: Context,
mChatList: List<Chat>,
imageUrl: String
) : RecyclerView.Adapter<ChatsAdapter.ViewHolder?>()
{
private val mContext: Context
private val mChatList: List<Chat>
private val imageUrl: String
var firebaseUser: FirebaseUser = FirebaseAuth.getInstance().currentUser!!
init {
this.mContext = mContext
this.mChatList = mChatList
this.imageUrl = imageUrl
}
override fun onCreateViewHolder(parent: ViewGroup, position: Int): ViewHolder
{
// message_item_left position == 0
// message_item_Right position == 1
return if (position == 1){
val view: View = LayoutInflater.from(mContext).inflate(com.example.whatsapp.R.layout.message_item_right,parent,false)
ViewHolder(view)
}else
{
val view: View = LayoutInflater.from(mContext).inflate(com.example.whatsapp.R.layout.message_item_left,parent,false)
ViewHolder(view)
}
}
override fun getItemCount(): Int {
//!! added coz of error
return mChatList.size
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
{
var profile_image: CircleImageView?= null
var show_text_message: TextView?=null
var left_image_view: ImageView?=null
var text_seen: TextView?=null
var right_image_view: ImageView?=null
init
{
profile_image = itemView.findViewById(R.id.profile_image)
show_text_message = itemView.findViewById(R.id.show_text_message)
left_image_view = itemView.findViewById(R.id.left_image_view)
text_seen = itemView.findViewById(R.id.text_seen)
right_image_view = itemView.findViewById(R.id.right_image_view)
}
}
override fun onBindViewHolder(holder: ViewHolder, position: Int)
{
val chat : Chat = mChatList[position]
Picasso.get().load(imageUrl).into(holder.profile_image)
//condition to check is a message is a text or image
//image messages
if (chat.getMessage().equals("sent you an image.") || !chat.getUrl().equals(""))
{
// image message - right side
// .equals() changed to ==
if (chat.getSender().equals(firebaseUser!!.uid))
{
holder.show_text_message!!.visibility == View.GONE
holder.right_image_view!!.visibility == View.VISIBLE
Picasso.get().load(chat.getUrl()).placeholder(R.drawable.profie).into(holder.right_image_view)
}else
// image message - left side
// !.equals() changed to !=
if (!chat.getSender().equals(firebaseUser!!.uid))
{
holder.show_text_message!!.visibility == View.GONE
holder.left_image_view!!.visibility == View.VISIBLE
Picasso.get().load(chat.getUrl()).placeholder(R.drawable.profie).into(holder.left_image_view)
}
}else
//text messages
{
holder.show_text_message!!.text = chat.getMessage()
}
// sent and seen message
if(position.equals(mChatList.size-1))
{
if (chat.isIsSeen())
{
holder.text_seen!!.text = "Seen"
if (chat.getMessage().equals("sent you an image.") && !chat.getUrl().equals(""))
{
// to move the seen text to bottom of the image
val lp: RelativeLayout.LayoutParams? = holder.text_seen!!.layoutParams as RelativeLayout.LayoutParams?
lp!!.setMargins(0,245, 10, 0 )
holder.text_seen!!.layoutParams = lp
}
}else
{
holder.text_seen!!.text = "Sent"
if (chat.getMessage().equals("sent you an image.") && !chat.getUrl().equals(""))
{
// to move the seen text to bottom of the image
val lp: RelativeLayout.LayoutParams? = holder.text_seen!!.layoutParams as RelativeLayout.LayoutParams?
lp!!.setMargins(0,245, 10, 0 )
holder.text_seen!!.layoutParams = lp
}
}
}
else
{
holder.text_seen!!.visibility = View.GONE
}
}
override fun getItemViewType(position: Int): Int
{
return if (mChatList[position].getSender().equals(firebaseUser!!.uid))
{
// refer onCreateViewHolder method
// sender = userid then update in message_item_right
1
}else
{
//else then update in message_item_right(receiver)
0
}
}
}
**logcat:**
2020-07-11 12:53:48.824 12690-12690/? E/Zygote: isWhitelistProcess - Process is Whitelisted
2020-07-11 12:53:48.825 12690-12690/? E/Zygote: accessInfo : 1
2020-07-11 12:53:48.850 12690-12690/? E/xample.whatsap: Unknown bits set in runtime_flags: 0x8000
2020-07-11 12:54:03.293 12690-12690/com.example.whatsapp E/InputMethodManager: prepareNavigationBarInfo() rootView is null
2020-07-11 12:54:07.139 12690-12690/com.example.whatsapp E/RecyclerView: No adapter attached; skipping layout
2020-07-11 12:54:27.814 12690-12690/com.example.whatsapp E/InputMethodManager: prepareNavigationBarInfo() rootView is null
2020-07-11 12:54:32.991 12690-12690/com.example.whatsapp E/RecyclerView: No adapter attached; skipping layout
2020-07-11 12:54:42.950 12690-12690/com.example.whatsapp E/DecorView: mWindow.mActivityCurrentConfig is null
2020-07-11 12:54:42.985 12690-12690/com.example.whatsapp E/DecorView: mWindow.mActivityCurrentConfig is null
2020-07-11 12:54:43.717 12690-12690/com.example.whatsapp E/ViewRootImpl: sendUserActionEvent() mView returned.
2020-07-11 12:54:43.830 12690-12690/com.example.whatsapp E/RecyclerView: No adapter attached; skipping layout
2020-07-11 12:54:43.866 12690-12690/com.example.whatsapp E/RecyclerView: No adapter attached; skipping layout
2020-07-11 12:55:07.741 12690-12690/com.example.whatsapp E/InputMethodManager: prepareNavigationBarInfo() rootView is null
2020-07-11 12:55:09.620 12690-12690/com.example.whatsapp E/RecyclerView: No adapter attached; skipping layout
2020-07-11 12:55:11.837 12690-12690/com.example.whatsapp E/DecorView: mWindow.mActivityCurrentConfig is null
2020-07-11 12:55:11.868 12690-12690/com.example.whatsapp E/DecorView: mWindow.mActivityCurrentConfig is null
2020-07-11 12:55:12.722 12690-12690/com.example.whatsapp E/ViewRootImpl: sendUserActionEvent() mView returned.
2020-07-11 12:55:12.814 12690-12690/com.example.whatsapp E/RecyclerView: No adapter attached; skipping layout
2020-07-11 12:55:12.863 12690-12690/com.example.whatsapp E/RecyclerView: No adapter attached; skipping layout
2020-07-11 12:55:34.379 12690-12690/com.example.whatsapp E/DecorView: mWindow.mActivityCurrentConfig is null
2020-07-11 12:55:38.764 12690-12690/com.example.whatsapp E/ViewRootImpl: sendUserActionEvent() mView returned.