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

Listener에 대한 질문입니다. (3시간동안 끙끙앓는중입니다...)

0 추천
안녕하세요 안드로이드 앱을 만들기 시작한 지 별로안되는 안린이입니다.

다른 사람의 눈에는 어떻게 보일지는 몰라도 제가 만든 앱을 테스트 결과 정상작동하고 이 코드에 동작순서를 보고있었는데 도저히 이해가 가지 않는 부분이 있어서 질문드립니다.

코드는 아래와 같습니다.

 

public void onCreate(BundleSaveIntanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.on_click_implements_activity);

 

btn_로그인 = (Button)findVeiwById(R.layout.로그인);                    //  XML ID = 로그인

btn_회원가입 = (Button)findVeiwById(R.layout.회원가입);    //  XML ID = 회원가입

btn_아이디찾기 = (Button)findVeiwById(R.layout.아이디찾기); //  XML ID = 아이디찾기

btn_비밀번호찾기 = (Button)findVeiwById(R.layout.비밀번호찾기); // XML ID = 비밀번호찾기

btn_개발자노트 = (Button)findVeiwById(R.layout.개발자노트); //  XML ID = 개발자노트

 

btn_로그인.setOnClickListener(this);

btn_회원가입.setOnClickListener(this);

btn_아이디찾기.setOnClickListener(this);

btn_비밀번호찾기.setOnClickListener(this);

btn_개발자노트.setOnClickListener(this);

}

 

@override

public void Onclick(View v) {  // 변수 v의 리턴값은 View의 형태.

switch(v.getId()){

case R.id.btn_로그인 :

Toast.makeText(this, "로그인 버튼을 클릭하셨습니다" , 70).show(); //1000는 1초

break;

case R.id.btn_아이디찾기 :

Toast.makeText(this, "아이디찾기 버튼을 클릭하셨습니다" , 70).show(); //1000는 1초

break;

case R.id.btn_비밀먼호찾기 :

Toast.makeText(this, "비밀번호찾기 버튼을 클릭하셨습니다" , 70).show(); //1000는 1초

break;

case R.id.btn_개발자노트 :

Toast.makeText(this, "개발자노트 버튼을 클릭하셨습니다" , 70).show(); //1000는 1초

break;

case R.id.btn_회원가입 :

Toast.makeText(this, "회원가입 버튼을 클릭하셨습니다" , 70).show(); //1000는 1초

break;

}}}

현재 자바에 대한 가장 기초적인 개념들은 머리에 둥실둥실 떠다니지만 용어들은 어느정도 알아들을 수 있습니다.

질문내용 :

1. btn_로그인.setOnClickListener(this)

//장시간의 구글링으로 얻은 정보로는 버튼 및 시각적 요소들은 view클래스를 상속한다는 점입니다.

제가 알고 있는 짧은 지식에서의 this는 this가 포함된 클래스에서의 일명 전역변수 ? 의 변수를 의미한다고 알고있는데 위의 this라는 코드는 아무리 봐도 그 의미가 아닌 것 같습니다.

1)btn_로그인은 현재 findviewbyid로인해 id를 구분하여 View를 찾으라는 의미로 제 스스로 해석했고

결국 의미를 넓혀서 view.setOnClickListener(this)라는 말이 되는거고 view에 setOnclickListener 메소드??(버튼 클릭시 이벤트를 발생) 를 이용하며 인자값은 this가 포함된 클래스의 변수를 불러온다는 말인대 도저히 말이안된다 생각합니다. 왜냐하면 현재 제가 작성한 클래스의 전역변수는 여려개가 있는대 this가 위의 전역변수를 ... 아무튼 전혀 말이안된다 생각합니다.

 

그러면 생각해 볼 수 있는 건 this는 view클래스의 전역변수를 의미하는 건지 아니면 setonclicklistener메소가 포함된 어떤 클래스의 전역변수를 의미하는 것이지 아무리 생각해봐도 답이 안나옵니다...

 

 

2. View v

View라는 데이터 타입의 변수 v 를 의미하는 것같은데 정확히 머라 정의할지 몰라서 질문드립니다.

3. 스위치 문에서의 v.getId()가 R.id.btn_로그인이 되는 과정

솔직히 1번질문 내용을 이해하면 바로 이해될거 같은대 ... 부탁드립니다..

 

긴글 읽어주셔서 감사합니다...
AndroidDdobot (260 포인트) 님이 2021년 11월 8일 질문

1개의 답변

+1 추천

질문이 상세하고 중요한 포인트를 물어보시고 있고 작업하신 코드도 같이 올려주셔서 답을 해드리기가 좋네요.

1. btn_로그인.setOnClickListener(this)

API문서를 보시면 궁금증을 해결하실 수 있습니다. setOnClickListener안에 들어가는 건 View.OnClickListener라는 인터페이스입니다. (https://developer.android.com/reference/android/view/View.OnClickListener 참조)

인터페이스는 뭔지 아실거예요. 그리고 this는 클래스(여기서는 아마도 액티비티일 것 같은데요)의 인스턴스를 가리키는 겁니다. 코드를 작성하는 시점에서는 인스턴스가 뭐가 될지를 알 수 없기 때문에, 런타임에 생성될 인스턴스를 "this"해서 사용하는 거죠. 이말은  setOnClickListener에 넘겨지는 this가 View.OnClickListener이기도 하다는 것이고 해당 액티비티가 View.OnClickListener구현하고 있다는 겁니다. 액티비티의 선언부를 살펴보시면 "implments View.OnClickListener" 이런 식으로 되어 있을 것이고 
 

@Override
public void onClick(View v) {

}

위와 같이 View.OnClickListener의 onClick메소드가  구현되어 있을 겁니다.

2. View v

OnClick메소드에 스위치문을 사용한 것은 여러개의 버튼이 똑같은 View.OnClickListener를 공유하기 때문입니다. 화면에서 버튼이 눌리게 되면 안드로이드 OS가 제일 먼저 버튼이 눌린 것을 센서를 통해 감지를 하고 이걸 어떻게 처리할 것인지 애플리케이션에 물어보게 됩니다. 애플리케이션내에서 눌린 버튼에 대한 onClickListener가 구현되어 있다면, 안드로이드 OS는 "이앱은 이 onClickListener안의 onClick메소드를 실행하기 원하는 구나" 하고 해석하여 처리하게 됩니다. 이 때 onClick메소드의 View 파라미터에 눌린 Button이 넘어오게 되는 거죠. 따라서 위처럼 View.OnClickListener를 여러뷰가 공유하는 경우는 View의 id를 이용해 구분하는 것이고 여러개의 case가 존재할 경우는  switch문이 적합한 문법이 됩니다. 

2번에서 3번도 자연스럽게 답이 된 것 같네요.

잘 이해가 되시면 좋겠네요.

 

spark (227,830 포인트) 님이 2021년 11월 8일 답변
우선 답변주신점 정말 감사합니다. 천천히 읽어보고 이해하도록 노력해볼게요!
안그래도 이거 해결안되면 잠 못잘거같아서.ㅠㅠ
첫번째 문제를 좀 더 쉽게 이해하려면  액티비티의 선언부에서 View.OnClickListener를 제거해 보세요. 아마 에러가 나서 컴파일이 안될 겁니다. 에러메세지를 보시면 좀 더 확실하게 감이 잡히시지 않을까 생각해요.
아 코드를 잘못작성했네요..
 findviewbyid값을 r.id.~~ 이런식으로 했어야됬는데...
링크 보내주신곳에서 setonclicklistener를 찾아봤는데 파라미터값을 view.onclickListener를받네요.
=>setonclicklistener(view.onclicklistener 1) 요렇게요
그리고 view를 클릭시 onclick(view v)를 호출한다고도 기술되어있네요.
혹은 boolean값을 받기도 한대요.
(2)번 답변은 정말 쉽게 설명해주셔서 알겠어요!
문제는 (1)에서
 "코드를 작성하는 시점에서는 인스턴스가 뭐가 될지를 알 수 없기 때문에, 런타임에 생성될 인스턴스를 "this"해서 사용하는 거죠."라고 말씀하셨는데 무슨말씀인지 모르겠어요 ㅠ
현재 제가 알고있는 인스턴스를 설명하라고하면 그 클래스의 정보를 담고 있는 일종의 변수??라고 말할거같은데 맞는지모르겠네요.
코딩을 하는 시점에서 인스턴스가 어떤것이 될 수 있는지 모르겠다라는 부분과 런타임에 생성될 인스턴스 그리고 this의 사용법을 모르는거 같습니다..
여태 this는 지역변수의 값을 전역 변수로 되돌려줄때 사용하는 함수구나 생각하고있었는데 여러가지 알아봐야겠네요..ㅠㅠ
조언감사합니다... 아직 감이 잘 안잡히네요
코드 원본은 집에 있어서... 지금 알바중이라 컴파일 해볼수가 없네요 ㅠㅠ
님의 코드가  MainActivity.java에 있는 MainActivity class에작성된 코드라고 하죠. MainActivty는 그냥 클래스, object이 아니죠.  Object은 생성자를 호출해서 생성하는 거구요. 그런데 님은 MainActivity를 직접 생성할 수가 없고, 안드로이드 시스템이 대신 생성을 해줍니다.

Object a = new Object();

이렇게 a 를 생성하면, 님이 a를 생성했으므로, a라는 인스턴스 변수를 통해 a 있는 메소드, getter, setter등에 접근할 수가 있죠. 그런데 MainActivity 의 경우는 그렇게 할 수가 없잖아요. 그럼 어떻게 a와 같이 instance variable을 사용할 수 있을까요? this 키워드가 바로 이 역할을 대신하게 해주는 겁니다. 대신 this는 외부에서 사용하는게 아니라 클래스 내부에서 사용하도록 제한되어 있습니다.
하나의 Object(ex자전거)를 만들려면 여러개의 class(페달,베어링,기어등)를 사용한다는 말씀이시죠 ? 그리고 object를 인스턴스화한 a는 여러개의 class를 사용할수 있고요. (object는 모든 클래스의 조상?이니까요.)
그리고 mainactivity를 컴파일 도중 안드로이드 시스템이 임의의? 객체를 생성해주고 저희는 코드를 작성할때 어떤 인스턴스가 생기는지 모르기때문에 this를 사용하여 그 인스턴스를 잡았다고 생각하면될까요??? 너무 소설인가요 ..?

여태 저는 this는 무조건 해당 클래스의 전역변수만을 지시한다라고 알고있었는대
this는 그 클래스를 컴파일 할 시에 생기는 임의의 객체 ?를 지칭하는 뜻이라고 인지하고있으면 괜찮을까요 ?
첫번째 문장은 맞는데, 제가 말한 포인트는 아니고 두번째 문장이 제가 말하고자 하는 포인트 맞습니다.
감사합니다.!!!!!!!!!!!!!
덕분에 당분간 이런 문제로 막히지 않을 것 같아요..!!
진도는 별로 나가지 못했지만 확실히 하나 챙겨가는 느낌이네요 정말 감사합니다.
혹시 또 이런 문제로 이상있을 시 spark님 답변 보면 바로 느낌 올 것 같습니다.
정말 감사합니다
소소하지만 행복하네요 진짜 ㅎㅎ;;
...