Read data then update it and finish by save it

Krisix :

I need you to help me to solve this problem:


The problem is that I want to read a String called coins from the database of Firebase and then turn it into an Integer value. Then when I push a button I want to add 1 to coins and after that, I turn it back into a String value to save it in the database.

So I tried to do this by using onDataChange to read the data and then use
int score = Integer.parseInt(coins) to turn it into an Integer value called score.

After that, I used onClickListener to add 1 to the integer, but Android Studio tells me:

Cannot resolve score

I don't know how to solve this issue so I would be so happy if you could help me with that thing.

This is my code :

public class HomeFragment extends Fragment {

    public HomeFragment() {
        // Required empty public constructor
    }

    //firebase
    FirebaseAuth firebaseAuth;
    FirebaseUser user;
    FirebaseDatabase firebaseDatabase;
    DatabaseReference databaseReference;
    StorageReference storageReference;

    //init view
    ImageButton addCoinsBtn;
    TextView coinsTv;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view =inflater.inflate(R.layout.fragment_home, container, false);

        //init firebase
        firebaseAuth = FirebaseAuth.getInstance();
        user = firebaseAuth.getCurrentUser();
        firebaseDatabase = FirebaseDatabase.getInstance();
        databaseReference = firebaseDatabase.getReference("Users");
        storageReference = getInstance().getReference();//firebase storage reference


        coinsTv=(TextView)view.findViewById(R.id.coinsTv);
        addCoinsBtn=(ImageButton)view.findViewById(R.id.add_coins);



        Query query = databaseReference.orderByChild("email").equalTo(user.getEmail());
        query.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                //check until required data get
                for (DataSnapshot ds : dataSnapshot.getChildren()){
                    //get data
                    String coins = ""+ds.child("coins").getValue();

                    int score = Integer.parseInt(coins);


                    //set data
                    coinsTv.setText(score);


                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

        addCoinsBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FirebaseDatabase database = FirebaseDatabase.getInstance();
                DatabaseReference coins = database.getReference("Users/"+ user.getUid() +"/coins");

                Integer  score =  score + 1;
                String scorefinal = Integer.toString(score);
                coins.setValue(scorefinal);


            }
        });

        return view;

    }

}

Thank you very much for all your bits of help.

Frank van Puffelen :

This is a basic scoping problem: variables only exist in the scope where you declare them.

So the int score that you declare in onDataChange is not available in the onClick method anymore.

And the Integer score that you declare in onClick is a new variable, which means that Integer score = score + 1; won't work, because the score on the right-hand side doesn't exist/have a value.

The solution is to declare score one level higher, as a member field of your `` class:

Integer score = -1;

Query query = databaseReference.orderByChild("email").equalTo(user.getEmail());
query.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        for (DataSnapshot ds : dataSnapshot.getChildren()){
            String coins = ""+ds.child("coins").getValue();

            score = Integer.parseInt(coins);

            coinsTv.setText(score);
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        throw databaseError.toException(); // never ignore errors
    }
});

addCoinsBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        FirebaseDatabase database = FirebaseDatabase.getInstance();
        DatabaseReference coinsRef = database.getReference("Users/"+ user.getUid() +"/coins");

        score = score + 1;
        String scorefinal = Integer.toString(score);
        coinsRef.setValue(scorefinal);
    }
});

I'd highly recommend storing the value as a number in the database, as it saves you constantly converting from string to integer and back. If you do this, the above code becomes:

Integer score = -1;

Query query = databaseReference.orderByChild("email").equalTo(user.getEmail());
query.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        for (DataSnapshot ds : dataSnapshot.getChildren()){
            score = ds.child("coins").getValue(Integer.class);
            coinsTv.setText(score);
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        throw databaseError.toException(); // never ignore errors
    }
});

addCoinsBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        FirebaseDatabase database = FirebaseDatabase.getInstance();
        DatabaseReference coinsRef = database.getReference("Users/"+ user.getUid() +"/coins");
        coinsRef.setValue(score+1);
    }
});

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=18625&siteId=1