ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Android] setOnClickListener(this)는 왜?
    Android 2017. 7. 13. 12:28


    Android 에서 view에 대한 onClick 처리를 하는방법은 여러가지가 있다.


    1) xml layout 파일에서 android:onClick="" 을 지정하는 방법

    2) view,setOnClickListener( new View.OnClickListener{ ... } ) [setOnClickListener에 익명클래스를 사용하는 방법]

    3) class에 View.OnClickListener를 implements 한 뒤 setOnClickListener(this) 를 사용하는 방법


    나는 주로 개발할 때 2번과 3번의 방법을 자주 사용한다.

    그 중 3번의 방법에 대해서 출근하다가 갑자기 setOnClickListener(this) 에서 this를 넣는데 어떻게 onClick() 으로 콜백이 받아지지? 라는 궁금증이 들었다.

    지금까지 너무 당연하게 쓰고있었고 왜 작동하는지 생각조차 안하고 손이 시키는 대로 3년째 개발을 하고있었다.

    이번엔 저 궁금증에 대해서 생각한것들과 직접 테스트 해본 것들을 작성하도록 하겠다.


    일단 View.OnClickListener를 확인해서 똑같은 작동을 하는 클래스를 생성해 보았다.

    public class TestView {

    private OnClickListener mOnClickListener;
    public void setOnClickListener(OnClickListener l) {
    mOnClickListener = l;
    }

    public interface OnClickListener {
    void onClick();
    }

    }

    실제 View class에도 이와 같은 구조로 선언이 되어있음을 확인 할 수 있다.

    그리고 TestView.OnClickListener를 구현하고 setOnClickListener(this)를 호출 하는 class를 만들어주었다.

    public class TestActivity extends Activity implements TestView.OnClickListener {


    private TestView mTestView;

    public void process() {

    mTestView = new TestView();
    mTestView.setOnClickListener(this);

    }

    @Override
    public void onClick() {

    }
    }

    평소에 Activity에서 TextView나 Button 등에 setOnClickListener를 사용하는 구조랑 똑같이 생겼다. 


    여기서부터 이제

    어떻게 TestView에 있는 setOnClickListener()는 OnClickListener를 매개변수로 전달 받고있는데,

    TestActivity setOnClickListener(this) 에서 전달하는 this는 TestActivity가 아닌가? 라는 궁금증이 들게되었다.


    처음에는

    public void setOnClickListener(OnClickListener l) {
    mOnClickListener = l;
    }

    이 전달 받는 부분에 디버그 브레이킹 포인트를 찍어서 매개변수 'l' 에 어떤게 들어있나 확인해보았다.

    그 결과 TestActivity 객체가 들어있음을 확인 할 수 있었고 매개변수 전달에 아무 이상이 없다는걸 깨닳았다.


    그렇다면 TestActivity는 OnClickListener와 인스턴스 타입이 같은가?

    이 부분을 테스트 해보기 위해 instanceof 로 검사해 보았다.

    public void setOnClickListener(OnClickListener l) {

    if (l instanceof OnClickListener) {
    // true
    }

    mOnClickListener = l;
    }

    if문은 true로 통과하였고 TestActivity에서도 같은 방식으로 thisTestView.OnClickListener의 형을 가지고 있는지 확인하였다.

    if (this instanceof TestView.OnClickListener) {
    // true
    }

    이 결과도 true였다.


    위의 조건문이 true 통과가 가능한것은 TestActivity에서 implements TestView.OnClickListener를 구현했기 때문이다.


    결국 TextView 등에서도 이와 같은 구조로 작동 할 것이고 mOnClickListener등의 변수가 interface OnClickListener의 onClick를 호출하여 TestActivity에 있는 onClick()에 콜백이 들어오게 될 것임을 알게 되었다.




    결론


    사실 지금까지 extends 만 다형성에 포함되는 범주로 생각하고 있었던것이 큰 착각이었다.

    너무 늦게 깨닫게 됬지만 implements도 구현을 하면 extends 처럼 형변환이 가능하다는것을 알게 된 궁금증이었다.


    자바의 다형성 그중에서도 업캐스팅, 다운캐스팅 그리고 상속, 구현에 대한 집합체 라고 생각된다.




    implements에 대한 범위를 검색 하다가 아래의 글이 도움이 되었다.

    http://startdash.tistory.com/entry/Java-instanceof-implemnts





    댓글

Designed by Tistory.