0

I am making a challenge between two users in my app using firebase database. in the challenge I store player1Uid and player2Uid(player1 is the player who started the challenge and player two is the player who will accept or refuse the challenge). I want to make a history of challenges so If the challenge is completed I store it in a list called"completedChallengesList" and if the challenge isn't completed yet I store it in a list called uncompleted challenge list.the code some times work fine but in other times it bring the data more than one time to the list.

this is my code that brings data :

    public void startAsynkTask() {
    //TODO : search for a solution to this error
    AsyncTask asyncTask = new AsyncTask() {
        @Override
        protected Boolean doInBackground(Object[] objects) {
            try {
                Socket sock = new Socket();
                sock.connect(new InetSocketAddress("8.8.8.8", 53), 1500);
                sock.close();
                return true;
            } catch (IOException e) {
                return false;
            }
        }

        @Override
        protected void onPostExecute(Object o) {
            if ((boolean) o) {
                clearLists();
                ChildEventListener generalChallengesListener = new ChildEventListener() {
                    @Override
                    public void onChildAdded(DataSnapshot dataSnapshot, String s) {

                        String challengeState = dataSnapshot.child("state").getValue().toString();
                        Log.v("Logging2", "onChildAdded");
                        if (challengeState.equals(uncompletedChallengeText)) {
                            getChallengeData(dataSnapshot, "onChildAdded");
                            view.onDataFound();
                        }
                    }

                    @Override
                    public void onChildChanged(DataSnapshot dataSnapshot, String s) {
                        //TODO : note that the only changing handled is when challenge moves from uncompleted to completed state
                        getChallengeData(dataSnapshot, "onChildChanged");
                        for (int i = 0; i < uncompletedChallengesList.size(); i++) {
                            if (uncompletedChallengesList.get(i).getId().equals(dataSnapshot.getKey())) {
                                uncompletedChallengesList.remove(i);
                                view.notifyAdapters(completedChallengesList.size(), uncompletedChallengesList.size());
                                break;
                            }
                        }
                        checkListsSizeAndAdjustViews();
                        view.hideProgressBar();
                    }

                    @Override
                    public void onChildRemoved(DataSnapshot dataSnapshot) {
                        startAsynkTask();
                    }

                    @Override
                    public void onChildMoved(DataSnapshot dataSnapshot, String s) {

                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {
                        //Toast.makeText(getActivity(), "فشل تحميل البيانات من فضلك تأكد من الاتصال بالانترنت", Toast.LENGTH_SHORT).show();
                        view.hideProgressBar();
                        Log.v("Logging", "error loading data : " + databaseError);
                    }
                };

                //this code gives data where current user is player 1
                player1Listener = challengesReference.orderByChild("player1Uid").equalTo(currentUserUid).addChildEventListener(generalChallengesListener);
                //this code gives data where current user is player 2
                player2Listener = challengesReference.orderByChild("player2Uid").equalTo(currentUserUid).addChildEventListener(generalChallengesListener);

                challengesReference.addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        onInitialDataLoaded();
                        Log.v("ChallengesFragPresenter", "completed list size :" + completedChallengesList + " , uncompleted list size : " + uncompletedChallengesList);
                        challengesReference.removeEventListener(this);
                    }


                    @Override
                    public void onCancelled(DatabaseError databaseError) {

                    }
                });
            } else {
                view.onNoInternetConnection();
            }
        }
    };

    asyncTask.execute();
}

public String getChallengeData(DataSnapshot dataSnapshot, String tag) {
    Log.v("ChallengesFragPresenter", "get challenge data called");
    Log.v("ChallengesFragPresenter", "completedChallengesList : " + completedChallengesList.size()
            + ", uncompletedChallengesList " + uncompletedChallengesList.size());
    view.startCompletedChallengesAdapter(completedChallengesList);
    view.startUnCompletedChallengesAdapter(uncompletedChallengesList);

    GenericTypeIndicator<List<Question>> t = new GenericTypeIndicator<List<Question>>() {
    };
    challenge = new Challenge();
    String challengeDate = dataSnapshot.child("date").getValue().toString();
    String challengeSubject = dataSnapshot.child("subject").getValue().toString();
    String challengeState = dataSnapshot.child("state").getValue().toString();
    String challengeId = dataSnapshot.getKey();
    ArrayList challengeQuestionsList = (ArrayList) dataSnapshot.child("questionsList").getValue(t);
    long player1Score = (long) dataSnapshot.child("player1score").getValue();
    long player2Score = (long) dataSnapshot.child("player2score").getValue();

    String player1Name = dataSnapshot.child("player1Name").getValue().toString();
    String player1Image = dataSnapshot.child("player1Image").getValue().toString();
    String player1Uid = dataSnapshot.child("player1Uid").getValue().toString();
    String player2Name = dataSnapshot.child("player2Name").getValue().toString();
    String player2Image = dataSnapshot.child("player2Image").getValue().toString();
    String player2Uid = dataSnapshot.child("player2Uid").getValue().toString();

    String challengerName, challengerImage;

    if (player1Uid.equals(currentUserUid)) {
        currentPlayer = 1;
        challengerName = player2Name;
        challengerImage = player2Image;
        challenge.setSecondChallengerUid(player2Uid);//second means that it is not the player who starts the challenge
        if (tag.equals("onChildAdded")) {
            player1childrenCount++;
        }
    } else {
        currentPlayer = 2;
        challengerName = player1Name;
        challengerImage = player1Image;
        challenge.setSecondChallengerUid(player1Uid);//second means that it is not the player who starts the challenge
        if (tag.equals("onChildAdded")) {
            player2childrenCount++;
        }
    }
    challenge.setCurrentPlayer(currentPlayer);
    challenge.setChallengerName(challengerName);
    challenge.setDate(challengeDate);
    challenge.setImage(challengerImage);
    challenge.setSubject(challengeSubject);
    challenge.setState(challengeState);
    challenge.setId(challengeId);
    challenge.setQuestionsList(challengeQuestionsList);
    String score;
    if (currentPlayer == 1) {
        score = player2Score + " : " + player1Score;
    } else {
        score = player1Score + " : " + player2Score;
    }
    challenge.setScore(score);
    if (challenge.getState().equals("اكتمل")) {
        view.showCompletedChallengesTv();
        if(!completedChallengesList.contains(challenge)) {
            completedChallengesList.add(0, challenge);
        }
        view.notifyAdapters(completedChallengesList.size(), uncompletedChallengesList.size());
    } else if (challenge.getState().equals(refusedChallengeText)) {
        view.showCompletedChallengesTv();
        if(!completedChallengesList.contains(challenge)) {
            completedChallengesList.add(0, challenge);
        }
        view.notifyAdapters(completedChallengesList.size(), uncompletedChallengesList.size());
    } else if (challenge.getState().equals(uncompletedChallengeText)) {
        view.showUncompletedChallengesTv();
        if(!uncompletedChallengesList.contains(challenge)) {
            uncompletedChallengesList.add(0, challenge);
        }
        view.notifyAdapters(completedChallengesList.size(), uncompletedChallengesList.size());
    }

    return player1Uid;
}

after long time of debugging I found that the method getChallengeData() is called more than one time when a new child added . I tried a lot to know why but I couldn't.

NOTE : I am using asynk task to check if there is internet connection or no before start loading data.

Mostafa Khaled
  • 372
  • 4
  • 16
  • 1
    This may depend on the database structure you have, as `childEventListeners` are fired multiple times if there are child nodes inside the node they are set on to listen. So it'd help if you could attach your database structure here. – PradyumanDixit Oct 15 '18 at 05:17
  • @Pradyuman Dixit I really have child nodes but I don't want onChild Added to work for them what can I do? – Mostafa Khaled Oct 15 '18 at 05:59
  • There's certainly no way for `childEventListeners` to not fire when there are child nodes, however you can use other `eventListeners` like `valueEventListener` or `singleValueEventListener`, You can read this answer to know more https://stackoverflow.com/a/52351637/8850875 – PradyumanDixit Oct 15 '18 at 06:01

1 Answers1

0

I think that your problem is, you are not removing your listner "generalChallengesListener", so multiple refereces will be created, so the onChildAdded will be excuted multiple times as the number of listners you created. So add a reference to your lister and know when you should remove it. Hope it will helps you =)

  • But I can't remove it because I need that when a new challenge started to be added to the challenges history – Mostafa Khaled Oct 15 '18 at 05:54
  • Yes, but you are creating multiple listners every time onChildRemoved is called, lets image u have created the first listner, then an item is removed from your database, another listner is created, know when, if an item is added in your database, onChildAdded will be called twice. –  Oct 15 '18 at 15:09