Как исправить исключения NullPointExceptions? - PullRequest
0 голосов
/ 06 августа 2020

Я кодировал социальное приложение, используя Kotlin. Недавно я добавил фрагмент поиска друзей в свое основное действие (основное действие состоит из трех фрагментов: домашняя страница, отклонение / принятие запроса на добавление в друзья и поиск друзей, которым вы можете отправлять запросы на добавление в друзья). Кроме того, у Main Activity есть макет вкладок, где это, прежде всего, фрагменты, и есть кнопка, которая направляет пользователей на страницу профиля. Вот где возникает проблема. Когда я пытаюсь выйти из системы, используя:

    mAuth!!.signOut()
    startActivity(Intent(applicationContext, LoginActivity::class.java))
    finishAffinity()

, я получаю сообщение об ошибке:

    Caused by: java.lang.IllegalAccessException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
    at com.example.realtimechat.findfriends.FindFriendsFragment$onViewCreated$1.onCancelled(FindFriendsFragment.kt:104)

Но эта ошибка присутствует только тогда, когда я посещаю фрагмент FindFriends перед нажатием на профиль кнопку страницы, чтобы перенаправить приложение на страницу профиля, где я могу выйти. Например, если я запускаю приложение (которое начинается с домашнего фрагмента) и сразу набираю go на страницу профиля, чтобы выйти, ошибка исчезнет, ​​и я успешно выйду из системы и перенаправлюсь на страницу входа. Однако, если я запускаю приложение, go для поиска фрагмента друзей, а затем go на страницу профиля для выхода из системы, я получаю сообщение об ошибке. Что-то я делаю не так?

(Кстати, у find friends есть вид ресайклера)

FindFriendsFragment.kt

package com.example.realtimechat.findfriends

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.realtimechat.R
import com.example.realtimechat.common.Constants
import com.example.realtimechat.common.NodeNames
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import com.google.firebase.database.*
import java.lang.NullPointerException

class FindFriendsFragment: Fragment() {

    private var rvFindFriends: RecyclerView? = null
    private var findFriendsAdapter: FindFriendAdapter? = null
    private var findFriendsModelList: MutableList<FindFriendModel> = ArrayList()
    private var tvEmptyFriendsList: TextView? = null

    private var databaseReference: DatabaseReference? = null
    private var currentUser: FirebaseUser? = null
    private var progressBar: View? = null

    private var databaseReferenceFriendRequests: DatabaseReference? = null

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_find_friends, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        rvFindFriends = view.findViewById(R.id.rvFindFriends)
        tvEmptyFriendsList = view.findViewById(R.id.tvEmptyFriendsList)
        progressBar = view.findViewById(R.id.progressBar)

        rvFindFriends!!.layoutManager = LinearLayoutManager(activity)

        findFriendsModelList = ArrayList()
        findFriendsAdapter = FindFriendAdapter(activity!!, findFriendsModelList)
        rvFindFriends!!.adapter = findFriendsAdapter

        databaseReference = FirebaseDatabase.getInstance().reference.child(NodeNames.USERS);
        currentUser  = FirebaseAuth.getInstance().currentUser;

        databaseReferenceFriendRequests = FirebaseDatabase.getInstance().reference.child(NodeNames.FRIEND_REQUESTS).child(currentUser!!.uid);

        tvEmptyFriendsList!!.visibility = View.VISIBLE;
        progressBar!!.visibility = View.VISIBLE;

        val query: Query = databaseReference!!.orderByChild(NodeNames.USERNAME)
        query.addValueEventListener(object: ValueEventListener{
            override fun onDataChange(snapshot: DataSnapshot) {
                progressBar?.visibility = View.GONE
                findFriendsModelList.clear()

                for(ds: DataSnapshot in snapshot.children){
                    val userId = ds.key
                    if(userId.equals(currentUser?.uid)){
                        continue
                    }

                    if(ds.child(NodeNames.USERNAME).value !=null){
                        val username = ds.child(NodeNames.USERNAME).value.toString()
                        val photoFileName = ds.child(NodeNames.PHOTO).value.toString()

                        databaseReferenceFriendRequests!!.child(userId!!).addListenerForSingleValueEvent(object: ValueEventListener{
                            override fun onDataChange(snapshot: DataSnapshot) {
                                if(snapshot.exists()){
                                    val requestType = snapshot.child(NodeNames.REQUEST_TYPE).value.toString()
                                    if(requestType == Constants.REQUEST_STATUS_SENT){
                                        findFriendsModelList.add(FindFriendModel(userId, photoFileName, username, true))
                                        findFriendsAdapter!!.notifyDataSetChanged()
                                    }
                                }else{
                                    findFriendsModelList.add(FindFriendModel(userId, photoFileName, username, false))
                                    findFriendsAdapter!!.notifyDataSetChanged()
                                }
                            }

                            override fun onCancelled(error: DatabaseError) {
                                progressBar?.visibility = View.GONE
                            }
                        })
                        progressBar?.visibility = View.GONE
                        tvEmptyFriendsList?.visibility = View.GONE
                    }
                }
            }

            override fun onCancelled(error: DatabaseError) {
                try {
                    progressBar?.visibility = View.GONE
                    Toast.makeText(activity, "Failed to fetch friend list ${error.message}", Toast.LENGTH_SHORT).show()
                }catch (e: NullPointerException){
                    throw(IllegalAccessException(e.message))
                }
            }
        })
    }
}

FindFriendsAdapter.kt

package com.example.realtimechat.findfriends

import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.GlideException
import com.example.realtimechat.R
import com.example.realtimechat.common.Constants
import com.example.realtimechat.common.NodeNames
import com.example.realtimechat.requests.RequestsFragment
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import com.google.firebase.database.DatabaseReference
import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.storage.FirebaseStorage


class FindFriendAdapter(private val context: Context,
                        private val findFriendModelList: List<FindFriendModel> = mutableListOf()) : RecyclerView.Adapter<FindFriendAdapter.FindFriendViewHolder>() {


    private var friendRequestDatabase: DatabaseReference? = null
    private var currentUser: FirebaseUser? = null
    private var userId: String? = null

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FindFriendAdapter.FindFriendViewHolder {
        val view: View = LayoutInflater.from(context).inflate(R.layout.custom_find_friends_layout, parent, false)
        return FindFriendViewHolder(view)
    }

    override fun onBindViewHolder(holder: FindFriendAdapter.FindFriendViewHolder, position: Int) {
        val friendModel = findFriendModelList[position]
        holder.tvUsername.text = friendModel.username

        val fileRef = FirebaseStorage.getInstance().reference.child(Constants.IMAGES_FOLDER + "/" + friendModel.photoFileName!!.substring(friendModel.photoFileName!!.lastIndexOf("/")+1))
        fileRef.downloadUrl.addOnSuccessListener {uri ->
            Glide.with(context)
                .load(uri)
                .placeholder(R.drawable.ic_profileicon)
                .error(R.drawable.ic_profileicon)
                .into(holder.ivProfile)
        }

        friendRequestDatabase = FirebaseDatabase.getInstance().reference.child(NodeNames.FRIEND_REQUESTS)
        currentUser = FirebaseAuth.getInstance().currentUser

        if(friendModel.requestSent!!){
            holder.btnSendRequest.visibility = View.GONE
            holder.pbRequest.visibility = View.VISIBLE
        }else{
            holder.btnSendRequest.visibility = View.VISIBLE
            holder.pbRequest.visibility = View.GONE
        }

        holder.btnSendRequest.setOnClickListener {
            holder.btnSendRequest.visibility = View.GONE
            holder.pbRequest.visibility = View.VISIBLE

            userId = friendModel.userId

            friendRequestDatabase!!.child(currentUser!!.uid).child(userId!!).child(NodeNames.REQUEST_TYPE).setValue(Constants.REQUEST_STATUS_SENT)
                .addOnCompleteListener { task ->
                    if(task.isSuccessful){
                        friendRequestDatabase!!.child(userId!!).child(currentUser!!.uid).child(NodeNames.REQUEST_TYPE)
                            .setValue(Constants.REQUEST_STATUS_RECEIVED)
                            .addOnCompleteListener { task ->
                                if(task.isSuccessful){
                                    Toast.makeText(context, "Request sent successfully!", Toast.LENGTH_SHORT).show()

                                    holder.btnSendRequest.visibility = View.GONE
                                    holder.pbRequest.visibility = View.GONE
                                    holder.btnCancelRequest.visibility = View.VISIBLE
                                }
                            }.addOnFailureListener{ exception ->
                                Toast.makeText(context, "Failed to send request ${exception.localizedMessage}", Toast.LENGTH_SHORT).show()

                                holder.btnSendRequest.visibility = View.VISIBLE
                                holder.pbRequest.visibility = View.GONE
                                holder.btnCancelRequest.visibility = View.GONE
                            }
                    }
                }.addOnFailureListener{ exception ->
                    Toast.makeText(context, "Failed to send request ${exception.localizedMessage}", Toast.LENGTH_SHORT).show()

                    holder.btnSendRequest.visibility = View.VISIBLE
                    holder.pbRequest.visibility = View.GONE
                    holder.btnCancelRequest.visibility = View.GONE
                }
        }

        holder.btnCancelRequest.setOnClickListener {
            holder.btnCancelRequest.visibility = View.GONE
            holder.pbRequest.visibility = View.VISIBLE

            userId = friendModel.userId

            friendRequestDatabase!!.child(currentUser!!.uid).child(userId!!).child(NodeNames.REQUEST_TYPE).setValue(null)
                .addOnCompleteListener { task ->
                    if(task.isSuccessful){
                        friendRequestDatabase!!.child(userId!!).child(currentUser!!.uid).child(NodeNames.REQUEST_TYPE)
                            .setValue(null)
                            .addOnCompleteListener { task ->
                                if(task.isSuccessful){
                                    Toast.makeText(context, "Request cancelled successfully!", Toast.LENGTH_SHORT).show()

                                    holder.btnSendRequest.visibility = View.VISIBLE
                                    holder.pbRequest.visibility = View.GONE
                                    holder.btnCancelRequest.visibility = View.GONE
                                }
                            }.addOnFailureListener{ exception ->
                                Toast.makeText(context, "Failed to cancel request ${exception.localizedMessage}", Toast.LENGTH_SHORT).show()

                                holder.btnSendRequest.visibility = View.GONE
                                holder.pbRequest.visibility = View.GONE
                                holder.btnCancelRequest.visibility = View.VISIBLE
                            }
                    }
                }.addOnFailureListener{ exception ->
                    Toast.makeText(context, "Failed to cancel request ${exception.localizedMessage}", Toast.LENGTH_SHORT).show()

                    holder.btnSendRequest.visibility = View.GONE
                    holder.pbRequest.visibility = View.GONE
                    holder.btnCancelRequest.visibility = View.VISIBLE
                }
        }
    }

    override fun getItemCount(): Int {
        return findFriendModelList.size
    }

    inner class FindFriendViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val ivProfile: ImageView = itemView.findViewById(R.id.ivProfilePic)
        val tvUsername: TextView = itemView.findViewById(R.id.tvUsername)
        val btnSendRequest: Button = itemView.findViewById(R.id.btnSendRequest)
        val btnCancelRequest: Button = itemView.findViewById(R.id.btnCancelRequest)
        val pbRequest: ProgressBar = itemView.findViewById(R.id.pbRequest)

    }
}

Код ошибки направляет меня к этой части кода:

override fun onCancelled(error: DatabaseError) {
                try {
                    progressBar?.visibility = View.GONE
                    Toast.makeText(activity, "Failed to fetch friend list ${error.message}", Toast.LENGTH_SHORT).show()
                }catch (e: NullPointerException){
                    throw(IllegalAccessException(e.message))
                }
            }

В частности , это:

throw(IllegalAccessException(e.message))

Однако исходный код был:

override fun onCancelled(error: DatabaseError) {
                    progressBar?.visibility = View.GONE
                    Toast.makeText(activity, "Failed to fetch friend list ${error.message}", Toast.LENGTH_SHORT).show()

            }

И ошибка направила меня на

                    Toast.makeText(activity, "Failed to fetch friend list ${error.message}", Toast.LENGTH_SHORT).show()

Мы будем очень благодарны за любую помощь / решение этой проблемы !!

ОБНОВЛЕНИЕ Я удалил тост из override fun onCancelled(error: DatabaseError) и код работает нормально. Однако мне нужно, чтобы этот тост был очевиден, так что есть способ обойти это?

1 Ответ

0 голосов
/ 06 августа 2020

Итак, я придумал возможное решение (оно работает, но я не уверен, что это лучший вариант):

Я в основном добавил условие:

if(isRemoving) {
                    Toast.makeText(context, "Unable to fetch friend requests: ${error.message}", Toast.LENGTH_SHORT).show();
                }

Снова , если у вас есть лучшее решение, мы будем очень признательны!

...