마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

리스너 내부에 리스너가 가능할까요?

0 추천
email_check.setOnClickListener(new View.OnClickListener(){
    @Override
    public void onClick(View view){
        isDict = false;
        userReference = databaseReference.child("users");
        userReference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                    String uuid = snapshot.getKey();    //문자열로 받기
                    Log.i(TAG, "유유" + uuid);
                    userReference.child(uuid).child("email").get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
                        @Override
                        public void onComplete(@NonNull Task<DataSnapshot> task) {
                            if (!task.isSuccessful()) { }
                            else {
                                String s = String.valueOf(task.getResult().getValue());
                                em = up_email.getText().toString();
                                if(s.equals(em)){
                                    isDict = true;
                                    Toast.makeText(getApplicationContext(), "아이디가 중복됩니다! ", Toast.LENGTH_SHORT).show();
                                }
                            }
                        }
                    });
                    if(isDict){
                        break;
                    }
                }
            }
            @Override
            public void onCancelled(DatabaseError databaseError) {
                // Getting Post failed, log a message
            }
        });
        if(isDict){
            Toast.makeText(getApplicationContext(), "아이디가 중복됩니다! ", Toast.LENGTH_SHORT).show();
        }
        else{
            Toast.makeText(getApplicationContext(), "아이디가 중복되지 않습니다! ", Toast.LENGTH_SHORT).show();
        }
    }
});

안녕하세요, 안드로이드 공부 중인 학생입니다.

코드는 다음과 같습니다.

onClick 콜백 메소드 내부에 또 다른 리스너를 등록해놓았는데요,

스냅샷으로 Firebase에서 uid 전체를 읽어오고 전체 uid 하위에 저장된 이메일을 읽어와서 이메일 중복검사를 하는 테스크입니다.

그런데 중복되는 아이디를 넣고 버튼을 눌러서 해당 토스트메세지가 출력되는 결과를 보면  처음에 아이디가 중복되지 않았다고 뜨고 이후에 아이디가 중복되었다는 메시지를 출력하게 됩니다.

아무래도 onClick 내부에 존재하는 리스너들이 비동기적이라 그런 것 같은데 해결방법이 있을까요?

알려주시면 감사하겠습니다.

Niaak (220 포인트) 님이 2022년 5월 15일 질문

1개의 답변

+1 추천
 
채택된 답변

말씀하신대로 Async로 동작을 하므로, ValueEventListener 밖에 있는 Toast 관련코드는 삭제하세요.

그리고 ValueEventListener.onDataChange에 있는 DataSnapShot 안에 이미 필요한 이메일 리스트가 들어는지 체크해 보시기 바랍니다. dataShanpshot.getChildren()으로 하위에 있는 문서들을 모두 체크할 수 있거든요. 내부에서 다시 document들을 일일이 파이어 베이스에서 가져와 검사하면 user 갯수가 많을 수록 성능상에 많은 차이가 있을 것 같은데요.

참고로, 코드의 가독성을 위해서 콜백 내부의 코드들은 리팩토링 메뉴를 통해서 외부로 빼네세요. 현재는 코드의 가독성이 상당히 떨어집니다. 아래처럼요.

email_check.setOnClickListener(new View.OnClickListener(){
    @Override
    public void onClick(View view){
        ...
        userReference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                usersDataChanged(dataSnapshot);
            }
            ..
        });
        
    }
});

priate void usersDataChanged(DataSnapshot dataSnapshot) {
    ...
}

 

spark (227,470 포인트) 님이 2022년 5월 15일 답변
Niaak님이 2022년 5월 17일 채택됨
앗! 확인해보니 하위 문서들이 포함되어 있네요! ValueEventListener를 살펴봐야겠네용..!!
이제 막 배우는 학부생이라 가독성 같은 부분은 신경을 못썼네요!
하나하나 꼼꼼히 체크해주셔서 감사합니다! :)
...