0

I receive null snapshot in only this two method

private fun getUserName() {

        databaseReference=FirebaseDatabase.getInstance("https://tailoring-e7e0c-default-rtdb.asia-southeast1.firebasedatabase.app/").getReference("Users")
        databaseReference.child(uAuth.currentUser?.uid.toString()).addValueEventListener(object : ValueEventListener {
            override fun onDataChange(snapshot: DataSnapshot) {
                var userList :User
                userList = snapshot.getValue(User::class.java)!!
                userName=userList?.cid.toString()
                Toast.makeText(this@ProductDetail,"Username detected",Toast.LENGTH_LONG).show()
            }
            override fun onCancelled(error: DatabaseError) {
            }
        })

    }
private fun getProductPic(prodImageURL:String) {

        storageReference= FirebaseStorage.getInstance().reference.child(prodImageURL)
        val localFile = File.createTempFile("tempImage","jpg")
        storageReference.getFile(localFile).addOnSuccessListener {
            val bitMap= BitmapFactory.decodeFile(localFile.absolutePath)
            viewBinding.picViewProd.setImageBitmap(bitMap)

        }
    }
class ProductDetail : AppCompatActivity() {
    private lateinit var databaseReference: DatabaseReference
    private lateinit var uAuth:FirebaseAuth
    private lateinit var storageReference: StorageReference
    private lateinit var viewBinding:ActivityProductDetailBinding
    private lateinit var adapter:commentAdapter
    private lateinit var tc:String
    private lateinit var commentList:ArrayList<commentContain>
    private lateinit var thisProductID:String
    private lateinit var dateTage :String
    private var userName :String=""
    private var tailorUID :String=""
    private var tailorName :String=""


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewBinding = ActivityProductDetailBinding.inflate(layoutInflater)
        val view = viewBinding.root
        setContentView(view)
        tc=getIntent().getStringExtra("tc").toString()
        thisProductID = getIntent().getStringExtra("prodNo").toString()
        uAuth = FirebaseAuth.getInstance()
        //Comment adapter and recycler view code
        commentList= ArrayList()

        getTailorName()
        getComment()
        adapter= commentAdapter(this,commentList)
        viewBinding.commentList.layoutManager=LinearLayoutManager(this)
        viewBinding.commentList.adapter=adapter
        getTimeTag()
        val currentUser = uAuth.currentUser?.uid
        val currentUserURL = "Users/$currentUser.jpg"
        getProductData()
        if(tc=="tailor"){
            viewBinding.btnOrderProduct.isVisible=false
        }

        viewBinding.btnOrderProduct.setOnClickListener {
            addOrder()
        }
        viewBinding.picViewTailor.setOnClickListener {
            val intent = Intent(this, TailorProfile::class.java)
            intent.putExtra("tc",tc)
            intent.putExtra("tuid",tailorUID)

            startActivity(intent)
        }
        viewBinding.sendButton.setOnClickListener{
            getUserName()
            val comment = viewBinding.messageBox.text.toString()

            addComment(thisProductID,userName,comment,dateTage,currentUserURL)

        }

    }

    private fun getUserName() {

        databaseReference=FirebaseDatabase.getInstance("https://tailoring-e7e0c-default-rtdb.asia-southeast1.firebasedatabase.app/").getReference("Users")
        databaseReference.child(uAuth.currentUser?.uid.toString()).addValueEventListener(object : ValueEventListener {
            override fun onDataChange(snapshot: DataSnapshot) {
                var userList :User
                userList = snapshot.getValue(User::class.java)!!
                userName=userList?.cid.toString()
                Toast.makeText(this@ProductDetail,"Username detected",Toast.LENGTH_LONG).show()
            }
            override fun onCancelled(error: DatabaseError) {
            }
        })

    }

    private fun getProductData() {
        databaseReference=FirebaseDatabase.getInstance("https://tailoring-e7e0c-default-rtdb.asia-southeast1.firebasedatabase.app/").reference
        databaseReference.child("Product").child(thisProductID).addValueEventListener(object: ValueEventListener {
            override fun onDataChange(snapshot: DataSnapshot) {
                val productData = snapshot.getValue<Product>()
                viewBinding.tvViewPrice.setText(productData?.price.toString())
                viewBinding.tvViewClothspants.setText(productData?.clothsPants.toString())
                viewBinding.tvViewFabric.setText(productData?.fabric.toString())
                viewBinding.tvViewHeight.setText(productData?.height.toString())
                viewBinding.tvViewHipBust.setText(productData?.hipBust.toString())
                viewBinding.tvViewSleeve.setText(productData?.sleeve.toString())
                viewBinding.tvViewStyleName.setText(productData?.styleName.toString())
                viewBinding.tvViewWaist.setText(productData?.waist.toString())

                tailorUID = productData?.tailorID.toString()
                getTailorPic(productData?.tailorID.toString())
                getProductPic(productData?.imageURL.toString())
            }

            override fun onCancelled(error: DatabaseError) {
                Toast.makeText(this@ProductDetail,"Some Things wrong in the database", Toast.LENGTH_SHORT).show()
            }

        }
        )
    }

    private fun getProductPic(prodImageURL:String) {

        storageReference= FirebaseStorage.getInstance().reference.child(prodImageURL)
        val localFile = File.createTempFile("tempImage","jpg")
        storageReference.getFile(localFile).addOnSuccessListener {
            val bitMap= BitmapFactory.decodeFile(localFile.absolutePath)
            viewBinding.picViewProd.setImageBitmap(bitMap)

        }
    }

    private fun getTailorName() {
        databaseReference=FirebaseDatabase.getInstance("https://tailoring-e7e0c-default-rtdb.asia-southeast1.firebasedatabase.app/").getReference("Users")
        databaseReference.child(tailorUID).addValueEventListener(object : ValueEventListener {

            override fun onDataChange(snapshot: DataSnapshot) {
                val userList = snapshot.getValue(User::class.java)!!
               tailorName=userList.cid.toString()
                viewBinding.tvPViewTailorName.setText(tailorName)
                Toast.makeText(this@ProductDetail,"Username detected",Toast.LENGTH_LONG).show()
            }

            override fun onCancelled(error: DatabaseError) {

            }
        })





    }

    private fun getTailorPic(tailorUID:String){

        storageReference= FirebaseStorage.getInstance().reference.child("Users/$tailorUID.jpg")
        val localFile = File.createTempFile("tempImage","jpg")
        storageReference.getFile(localFile).addOnSuccessListener {
            val bitMap= BitmapFactory.decodeFile(localFile.absolutePath)
            viewBinding.picViewTailor.setImageBitmap(bitMap)

        }
    }

    private fun getComment() {
        databaseReference=FirebaseDatabase.getInstance().getReference()
        databaseReference.child("Comment").addValueEventListener(object : ValueEventListener {
            override fun onDataChange(snapshot: DataSnapshot) {
                commentList.clear()
                for(postSnapshot in snapshot.children){
                    val currentComment = postSnapshot.getValue(commentContain::class.java)
                    if(currentComment?.productID==thisProductID){
                        commentList.add(currentComment!!)
                    }

                }
                adapter.notifyDataSetChanged()
            }

            override fun onCancelled(error: DatabaseError) {

            }

        })

    }

    private fun addOrder() {
        val intent = Intent(this, NewCustomOrder::class.java)
        intent.putExtra("tc",tc)
        intent.putExtra("prodNo",thisProductID)
        startActivity(intent)
    }

    private fun addComment(productID:String,senderID:String?,comment:String,dateTage:String,currentUserURL:String){
        val newComment = commentContain(uAuth.currentUser?.uid,senderID,comment,dateTage,currentUserURL,productID)
        databaseReference=FirebaseDatabase.getInstance().reference
        databaseReference.child("Comment").child(commentList.size.toString()).setValue(newComment).addOnFailureListener{
            Toast.makeText(this,"Some thing wrong for real time database", Toast.LENGTH_SHORT).show()
        }.addOnSuccessListener {
            Toast.makeText(this,"Comment is added", Toast.LENGTH_SHORT).show()
        }
    }

    private fun getTimeTag() {
        val formatter = SimpleDateFormat("yyyy_MM_dd", Locale.getDefault())
        val now = Date()
        dateTage=formatter.format(now).toString()
    }


    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        super.onCreateOptionsMenu(menu)
        getMenuInflater().inflate(R.menu.all_menu,menu)

        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        super.onOptionsItemSelected(item)
        if(item.itemId==R.id.toProfile){
            val intent = Intent(this, TailorProfile::class.java)
            intent.putExtra("tc",tc)
            intent.putExtra("tuid",uAuth.currentUser?.uid)
            finish()
            startActivity(intent)
        }
        else if(item.itemId == R.id.toHome){
            val intent = Intent(this, ProductList::class.java)
            intent.putExtra("tc",tc)
            finish()
            startActivity(intent)
        }else if(item.itemId == R.id.logout){
            val intent = Intent(this, Ground::class.java)
            uAuth.signOut()
            finish()
            startActivity(intent)
        }
        return true
    }


}

The only problem is the getUserName and getTailorName return null at all,which is cause by the snapshot return a null value. I have tried all the method of get data from firebase realtime database, but all of them meets same problem. The weird thing is only the two function meet that problem. Any one can help me please?

below is the picture output enter image description here

  • Data is loaded from Firebase asynchronously, since it typically has to come from the server. Instead of making the app (and the user) wait for that data, your main code continues to execute. Then when the data is available, your `onDataChange` gets called with it. What this means in practice is that your `return userName` executes before the `userName=userList?.cid.toString()` is ever called. If you set breakpoints on these lines and run in the debugger, or adding logging to them, you can see this happening. – Frank van Puffelen Dec 15 '21 at 04:44
  • The solution is always the same: any code that needs the data from the database needs to be inside `onDataChange`, be called from there, or be otherwise synchronized. – Frank van Puffelen Dec 15 '21 at 04:45
  • You may also find [this](https://stackoverflow.com/questions/57330766/why-does-my-function-that-calls-an-api-return-an-empty-or-null-value/) question useful. – Tyler V Dec 15 '21 at 05:00
  • @FrankvanPuffelen That problem is solve by using a private var to get data. But the data I get is null...... The snapshot return me a null data at all. – student aaa Dec 15 '21 at 05:19
  • There is no way you can do that. Firebase API is asynchronous. So please check the duplicate to see how can you solve this using a callback. You might also be interested in reading this article, [How to read data from Firebase Realtime Database using get()?](https://medium.com/firebase-tips-tricks/how-to-read-data-from-firebase-realtime-database-using-get-269ef3e179c5). – Alex Mamo Dec 15 '21 at 07:38

0 Answers0