【问题标题】:How do you fix NullPointExceptions?你如何修复 NullPointErexception?
【发布时间】:2020-11-26 23:24:25
【问题描述】:

我一直在使用 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 片段时才会出现此错误。例如,如果我启动应用程序(以主页片段开头)并立即转到个人资料页面退出,错误消失了,我成功退出并重定向到登录页面。但是,如果我启动应用程序,去寻找朋友片段,然后去个人资料页面注销,我会收到错误消息。是不是我做错了什么?

(顺便找朋友有recycler view)

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) 中删除了 Toast,代码运行正常。但是,我需要这个 Toast 是显而易见的,那么有没有办法解决这个问题?

【问题讨论】:

  • databaseReferenceFriendRequests 可能为 Null 并导致问题
  • @chandmohd 我该如何解决这个问题?
  • @chandmohd 我已经添加了一个条件 if(databaseReferenceFriendRequests!=null) ,但错误仍然存​​在,所以我认为这不是解决方案
  • 一般来说,你应该避免使用var和nullable类型。如果你这样做了,请用null 支票保护他们。浏览您的代码,我找不到您甚至拥有nullable 类型的理由。如果你完全摆脱它,你将没有任何null-pointer exceptions。
  • 不要使用!!,除非您确定某些内容不能为空。通常没有必要使用它。

标签: android firebase authentication kotlin nullpointerexception


【解决方案1】:

所以我想出了一个可能的解决方案(它有效,但我不确定它是否是最佳选择):

我已经基本添加了条件:

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

再次,如果您有更好的解决方案,将不胜感激!

【讨论】:

    猜你喜欢
    • 2020-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-01
    • 2021-06-16
    相关资源
    最近更新 更多