[java] Android : 버튼 클릭 처리 방법

비 Java 및 비 Android 영역에서 탄탄한 경험을 쌓은 저는 Android를 배우고 있습니다.

다른 영역과 많은 혼동이 있습니다. 그중 하나는 버튼 클릭을 처리하는 방법입니다. 최소한 4 가지 방법 (!!!)이 있으며 여기에 간략하게 나열되어 있습니다.

일관성을 위해 다음과 같이 나열합니다.

  1. View.OnClickListener활동에 클래스 의 멤버를 onClick두고 onCreate활동 메소드의 논리를 처리 할 인스턴스에 할당합니다 .

  2. ‘onCreate’액티비티 메서드에서 ‘onClickListener’를 생성하고 setOnClickListener를 사용하여 버튼에 할당합니다.

  3. 활동 자체에서 ‘onClickListener’를 구현하고 ‘this’를 버튼의 리스너로 지정하십시오. 활동에 버튼이 적은 경우 버튼 ID를 분석하여 적절한 버튼에 대한 ‘onClick’핸들러를 실행해야합니다.

  4. ‘onClick’로직을 구현하는 활동에 대한 공용 메소드를 가지고 활동 xml 선언의 단추에 할당합니다.

질문 1:

그 모든 방법이 있습니까? 다른 옵션이 있습니까? (다른 건 필요 없어 그냥 궁금해)

나에게 가장 직관적 인 방법은 최신 방법 일 것입니다. 입력 할 코드의 양이 가장 적고 가장 읽기 쉽습니다 (적어도 나에게는).

하지만이 접근 방식이 널리 사용되는 것은 아닙니다. 그것을 사용하는 것에 대한 단점은 무엇입니까?

질문 # 2 :

각 방법의 장단점은 무엇입니까? 귀하의 경험이나 좋은 링크를 공유하십시오.

모든 피드백을 환영합니다!

추신 : Google에이 주제에 대한 무언가를 찾아 보려고했지만 내가 찾은 유일한 것은 “어떻게”그 일을 수행하는지 설명하는 것이지 왜 좋은지 나쁜지가 아닙니다.



답변

질문 1 : 안타깝게도 당신이 가장 직관적이라고 말하는 것은 안드로이드에서 가장 적게 사용되는 것입니다. 이해했듯이 UI (XML)와 계산 기능 (Java 클래스 파일)을 분리해야합니다. 또한 더 쉽게 디버깅 할 수 있습니다. 실제로 이런 식으로 읽고 Android imo에 대해 생각하는 것이 훨씬 쉽습니다.

질문 2 : 주로 사용되는 두 가지는 # 2와 # 3이라고 생각합니다. 예를 들어 Button clickButton을 사용하겠습니다.

2

익명 클래스의 형태입니다.

Button clickButton = (Button) findViewById(R.id.clickButton);
clickButton.setOnClickListener( new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                ***Do what you want with the click here***
            }
        });

이것은 findViewById로 버튼 변수가 설정된 바로 옆에 onClick 메서드가 있기 때문에 제가 가장 좋아하는 것입니다. 이 clickButton Button View를 다루는 모든 것이 여기에 있다는 것이 매우 깔끔하고 깔끔해 보입니다.

내 동료가 말한 단점은 onclick 리스너가 필요한 뷰가 많다는 것입니다. onCreate의 길이가 매우 길다는 것을 알 수 있습니다. 그래서 그가 사용하는 것을 좋아하는 이유 :

5 개의 clickButton이 있다고 가정 해 보겠습니다.

Activity / Fragment가 OnClickListener를 구현하는지 확인하십시오.

// in OnCreate

Button mClickButton1 = (Button)findViewById(R.id.clickButton1);
mClickButton1.setOnClickListener(this);
Button mClickButton2 = (Button)findViewById(R.id.clickButton2);
mClickButton2.setOnClickListener(this);
Button mClickButton3 = (Button)findViewById(R.id.clickButton3);
mClickButton3.setOnClickListener(this);
Button mClickButton4 = (Button)findViewById(R.id.clickButton4);
mClickButton4.setOnClickListener(this);
Button mClickButton5 = (Button)findViewById(R.id.clickButton5);
mClickButton5.setOnClickListener(this);


// somewhere else in your code

public void onClick(View v) {
    switch (v.getId()) {
        case  R.id.clickButton1: {
            // do something for button 1 click
            break;
        }

        case R.id.clickButton2: {
            // do something for button 2 click
            break;
        }

        //.... etc
    }
}

내 동료가 설명하는이 방법은 모든 onClick 계산이 onCreate 메소드를 복잡하게하지 않고 한곳에서 처리되므로 그의 눈에는 깔끔합니다. 그러나 내가 보는 단점은 다음과 같습니다.

  1. 자신을 바라보고,
  2. onClick 메서드에서 사용하는 onCreate에있을 수있는 다른 개체는 필드로 만들어야합니다.

더 많은 정보를 원하시면 알려주세요. 꽤 긴 질문이기 때문에 귀하의 질문에 완전히 대답하지 않았습니다. 그리고 사이트를 찾으면 답을 넓힐 것입니다. 지금은 경험을 제공하고 있습니다.


답변

# 1 레이아웃에 생성되지 않은 버튼이있을 때 마지막 버튼을 자주 사용합니다.

ProGuard와 같은 소스 난독 처리기 를 사용할 때 난독 화 되지 않도록 활동에 이러한 메서드를 표시해야 하므로 실제로 사용하고 비즈니스 응용 프로그램에서 사용하는 경우 여기에 특히주의하십시오 .

이 접근 방식을 사용하여 일종의 컴파일 시간 보안을 보관하려면 Android Lint ( 예제 )를 살펴보세요 .


# 2 모든 방법의 장단점 은 거의 동일하며 교훈은 다음과 같아야합니다.

가장 적합하거나 가장 직관적 인 것을 사용하십시오.

OnClickListener여러 버튼 인스턴스에 동일한 항목을 할당해야하는 경우 클래스 범위 (# 1)에 저장합니다. Button에 대한 간단한 리스너가 필요한 경우 익명으로 구현하십시오.

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        // Take action.
    }
});

나는 OnClickListener활동에서를 구현하지 않는 경향 이 있습니다. 이것은 때때로 약간 혼란스러워집니다 (특히 여러 다른 이벤트 핸들러를 구현하고 아무도 무엇을 this하고 있는지 아무도 모르는 경우 ).


답변

나는 옵션 4를 선호하지만 Grails, Groovy 및 JavaFX에서 너무 많은 작업을 수행하기 때문에 직관적으로 이해됩니다. 뷰와 컨트롤러 사이의 “매직”연결은 모두 일반적입니다. 방법의 이름을 잘 지정하는 것이 중요합니다.

보기에서 버튼 또는 다른 위젯에 onClick 메서드를 추가합니다.

    android:clickable="true"
    android:onClick="onButtonClickCancel"

그런 다음 클래스에서 메서드를 처리합니다.

public void onButtonClickCancel(View view) {
    Toast.makeText(this, "Cancel pressed", Toast.LENGTH_LONG).show();
}

다시 말하지만, 방법의 이름을 명확하게 지정하십시오. 어쨌든해야 할 일이 있으면 유지 관리가 두 번째 특성이됩니다.

한 가지 큰 장점은 이제 메서드에 대한 단위 테스트를 작성할 수 있다는 것입니다. 옵션 1은이를 수행 할 수 있지만 2와 3은 더 어렵습니다.


답변

가장 많이 사용되는 방법은 익명 선언입니다.

    Button send = (Button) findViewById(R.id.buttonSend);
    send.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // handle click
        }
    });

또한 View.OnClickListener 객체를 생성하고 나중에 버튼으로 설정할 수 있지만, 예를 들어 여전히 onClick 메서드를 재정의해야합니다.

View.OnClickListener listener = new View.OnClickListener(){
     @Override
        public void onClick(View v) {
            // handle click
        }
}   
Button send = (Button) findViewById(R.id.buttonSend);
send.setOnClickListener(listener);

활동이 OnClickListener 인터페이스를 구현할 때 활동 수준에서 onClick (View v) 메서드를 재정의해야합니다. 그런 다음이 액티비티를 버튼에 대한 리스너로 지정할 수 있습니다. 이미 인터페이스를 구현하고 onClick () 메서드를 재정의하기 때문입니다.

public class MyActivity extends Activity implements View.OnClickListener{


    @Override
    public void onClick(View v) {
        // handle click
    }


    @Override
    public void onCreate(Bundle b) {
        Button send = (Button) findViewById(R.id.buttonSend);
        send.setOnClickListener(this);
    }

}

(imho) 여러 버튼에 동일한 핸들러가있을 때 사용되는 4 번째 접근 방식으로 액티비티 클래스에서 하나의 메서드를 선언하고이 메서드를 xml 레이아웃의 여러 버튼에 할당 할 수 있습니다. 또한 하나의 버튼에 대해 하나의 메서드를 생성 할 수 있습니다. 활동 클래스 내부에 핸들러를 선언하는 것을 선호합니다.


답변

옵션 1과 2는 코드를 복잡하게 만드는 내부 클래스를 사용하는 것입니다. 옵션 2는 모든 버튼에 대해 하나의 리스너가 있기 때문에 다소 지저분합니다. 버튼 수가 적어도 괜찮습니다. 옵션 4의 경우 xml 및 Java 코드로 돌아가서 네 번째로 돌아 가야하므로 디버깅하기가 더 어려울 것이라고 생각합니다. 저는 개인적으로 여러 버튼 클릭을 처리해야 할 때 옵션 3을 사용합니다.


답변

내 샘플, Android 스튜디오 2.1에서 테스트 됨

XML 레이아웃에서 버튼 정의

<Button
    android:id="@+id/btn1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

자바 맥동 감지

Button clickButton = (Button) findViewById(R.id.btn1);
if (clickButton != null) {
    clickButton.setOnClickListener( new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            /***Do what you want with the click here***/
        }
    });
}


답변

ASP 질문 2에서 언급 한 것을 더 쉽게 만들기 위해 이와 같은 람다 메서드를 사용하여 변수 메모리를 절약하고 뷰 클래스에서 위아래로 탐색하지 않도록 할 수 있습니다.

//method 1
findViewById(R.id.buttonSend).setOnClickListener(v -> {
          // handle click
});

그러나 클릭 이벤트를 메서드에서 한 번에 버튼에 적용하려면.

@D의 질문 3을 사용할 수 있습니다. 트란 대답. 그러나 뷰 클래스를 View.OnClickListener.

다른 질문 # 3을 적절하게 사용하기 위해