2

I previously asked the almost same question. But the answer wasn't that good or just not good enough. I wanted to start again and now I have a lot of problems.

Here is the post.

Making a database-voting app

So for now I have another idea.

This time there is only one value which counts the votes, but the app don't get the actual amount of the value "count".

Here is my code:

database = FirebaseDatabase.getInstance();
names= database.getReference("Test");

final Name name = new Name(txtName.getText().toString(), score);
names.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull final DataSnapshot dataSnapshot) {
            if (dataSnapshot.child(name.getName()).exists()) {
                up.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        names.addValueEventListener(new ValueEventListener() {
                            @Override
                            public void onDataChange(DataSnapshot dataSnapshot) {
                                score = dataSnapshot.child("Test").child("Name").getValue(long.class);
                                score += 1;
                                final Name name = new Name(txtName.getText().toString(), score);
                                try {
                                    names.child(name.getName()).setValue(name);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }

                            @Override
                            public void onCancelled(DatabaseError databaseError) {
                            }
                        });

                        Toast.makeText(Result.this, "Thank you for voting", Toast.LENGTH_SHORT).show();

                        Intent homeIntent3 = new Intent(Result.this, StartActivity.class);
                        startActivity(homeIntent3);
                    }
                });

 

Here's the database

enter image description here

So if the name doesn't exist I easily can add the up/down vote with score = 1 or score = -1.

But if the name exists, there is a problem with changing the score value.

The app is crashing with the following error

java.lang.NullPointerException: Attempt to invoke virtual method 'long java.lang.Long.longValue()' on a null object reference
                  at user.prof.name.Activities.Result$1$1$1.onDataChange(Result.java:80)
                  at com.google.firebase.database.obfuscated.zzap.zza(com.google.firebase:firebase-database@@16.0.3:75)
                  at com.google.firebase.database.obfuscated.zzca.zza(com.google.firebase:firebase-database@@16.0.3:63)
                  at com.google.firebase.database.obfuscated.zzcd$1.run(com.google.firebase:firebase-database@@16.0.3:55)
                  at android.os.Handler.handleCallback(Handler.java:789)
                  at android.os.Handler.dispatchMessage(Handler.java:98)
                  at android.os.Looper.loop(Looper.java:251)
                  at android.app.ActivityThread.main(ActivityThread.java:6589)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

And this is the error line in the code

score = dataSnapshot.child("Test").child("Name").getValue(long.class);

I'm not an expert in the database programming, but what is wrong? The wrong child?

I also tried to save the "score" as a String and parse it to a long value. But that's not also working.

halfer
  • 19,824
  • 17
  • 99
  • 186
Hansi
  • 97
  • 3
  • 13
  • 1
    First thing I see is that `Name` is not an attribute for itself and also you have a separate node for storing the actual value. I would do the code like this: `score = dataSnapshot.child("Test").child("Name1").child("Name1").getValue(String.class);` – PradyumanDixit Oct 12 '18 at 10:59
  • Thank you. But with this I'm getting the same error – Hansi Oct 12 '18 at 12:34

1 Answers1

5

You aren't getting anything because the name of your Name property is in every child is different. To solve this, you should have the same name under each child like this:

Firebase-root
  |
  --- test
       |
       --- Name1
       |     |
       |     --- name: "Name1"
       |     |
       |     --- score: 0
       |
       --- Name2
             |
             --- name: "Name2"
             |
             --- score: 15

See, the name of the name property is now always name and not name1, name2 and so on.

To get the value of your score properties within all objects, please use the following lines of code:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query query = rootRef.child("test").orderByChild("name");
ValueEventListener valueEventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            long score = ds.child("score").getValue(Long.class);
            Log.d(TAG, "Score: " + score);
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        Log.d(TAG, databaseError.getMessage());
    }
};
query.addListenerForSingleValueEvent(valueEventListener);

The output in your logcat will be:

Score: 0
Score: 15

Please also note that I have passed to the getValue(Long.class), the Long class and not the primitive long.

Edit:

To edit a single entry, then you should use the following lines of code:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Map<String, Object> map = new HashMap<>();
map.put("score", 5);
rootRef.child("test").child("Name1").updateChildren(map);

The score property in the first object will be changed from 0 to 5. If you think that your score property will updated in an multi user environment, then you should use FirebaseTransactions as explained my answer from this post.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Thank you @Alex Mamo. I get the whole list and I can increase all of them and change the score value, but how can I edit only one entry? I don't get it... So if Name1 already exists, how can I only increase that entry? I've tried a few things, but nothing is working... – Hansi Oct 12 '18 at 12:31
  • Sorry. Unfortunately, the question has not yet been answered 100%. If I accept the answer now, then unfortunately no one helps me anymore. I have edited on my first answer to your answer. – Hansi Oct 12 '18 at 12:50
  • 1
    I see the edited comment. So if you want to edit a single entry then please see my updated answer. Is it ok now? – Alex Mamo Oct 12 '18 at 12:58
  • Thank you very much! This is the right way. I only have two mistakes. How can I get the actual value of the score? If I'm adding `score--; map.put("count", score);` then it always starts at 0 and counts one down. When I'm adding `score++;` it counts infinitely high. A for-loop it counts also till infinity – Hansi Oct 12 '18 at 17:43
  • 1
    Good to hear that and you're welcome Hansi! "How can I get the actual value of the score?" You should post another fresh question for that, so me and other users can help you. – Alex Mamo Oct 13 '18 at 03:57