OnClickListener 내부에서 많은 항목에 액세스 할 수 없습니다. 어떻게 접근합니까?


79

OnClickListener 내부에서 다음과 같이 범위 "외부"에있는 대부분의 변수에 액세스 할 수 없습니다.

findViewById(R.id.Button01).setOnClickListener(new OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                Intent mainApps = new Intent(Intent.ACTION_MAIN);
                mainApps.addCategory(Intent.CATEGORY_LAUNCHER);
                List<ActivityInfo> activities = this.getPackageManager().queryIntentActivities(mainApps, 0);
                /*
                Intent intent = new Intent("com.sygic.drive/com.sygic/drive/.SygicDriveActivity");
                startActivity(intent);*/
            }

        });

이 예제에서는 PacketManager를 가져와야하는데 OnClickListener 내부에 Context를 사용할 수 없기 때문에 가져올 수 없습니다.

외부에서 정적 참조를 만들어 내부에서 사용할 수 있지만 그게 맞습니까? 항상 그렇게해야하는 게 이상해 보입니까?

답변:


231

this코드 MyActivity.this에서 MyActivity가 Activity 하위 클래스의 클래스 이름 인 것으로 바꿉니다 .

설명 : 코드의이 부분을 사용할 때 익명 내부 클래스를 작성하고 있습니다. 익명 내부 클래스는 작성되는 클래스
new OnClickListener() {
의 인스턴스에 대한 참조를 가지고 있습니다. findViewById가 다음과 같기 때문에 활동 서브 클래스 내부에서 작성하는 것처럼 보입니다. 활동 방법. 활동은 컨텍스트이므로 자동으로 보유한 참조를 사용하기 만하면됩니다.


1
"MyActivity.this"를 찾기 위해 잠시 인터넷 검색을했습니다. 지금은 너무 간단 해 보입니다. 정보에 대해서 감사드립니다!
TCCV 2011

오류를 발생시키는 변수에 액세스하는 것은 Cannot refer to a non-final variable table inside an inner class defined in a different method어떻습니까? 을 통해 액세스 할 수 없습니다 MyActivity.this.
Michael

그것들은 지역 변수입니다. 변경되지 않으면 최종 선언으로 변경할 수 있습니다. 변경되는 경우 내부 클래스가 정의되기 전에 최종 버전을 바로 정의 할 수 있습니다. 예 : final int myFinalErrorCode = errorCode. 그렇지 않으면 액세스하는 활동이나 내부 클래스에서 구성원을 만들고 설정하는 것과 같은 작업을 수행해야합니다.
Lance Nanek 2015 년

나는 이것이 동작하는 것을 이해하지 못하지만 당신이 말한대로 작동합니다 Activity.this.doStg(). @LanceNanek 여기에 더 자세한 설명이있는 URL을 첨부 할 수 있습니까? 어떻게 든 반응 형 프로그래밍과 관련이 있습니까?
murt

여기에 "ShadowTest.this"예를 참조하십시오 docs.oracle.com/javase/tutorial/java/javaOO/nested.html
랜스 Nanek

10

클래스에서 OnClickListener 인터페이스를 구현하고 익명의 내부 클래스가 필요하지 않도록 할 수도 있습니다. 그런 다음 다음과 같이 클릭 리스너를 설정합니다.

findViewById(R.id.Button01).setOnClickListener(this);

하나의 리스너를 사용하는 여러 버튼이있는 경우 view.getId () (R.id의 뷰 ID에 해당)와 함께 switch 문을 사용하여 구분할 수 있습니다.


4

할 수있는 몇 가지 작업이 있습니다. onClickListener를 구현하는 내부 클래스를 만들고 필요한 인수를 클래스 생성자에 전달할 수 있습니다. 나는 여전히 가장 깨끗한 접근 방식을 찾지 못했습니다. 나는 보통 내 행동을 수행하는 다른 방법을 만듭니다. 따라서 onClick (View v)에서 이와 같은 작업을 수행합니다.

onClick(View v){doMyAction(myParams)}

private void doMyAction(Object params){//do stuff}

그리고 리스너 메소드에서 리스너 외부의 메소드로 필요한 매개 변수를 전달하면됩니다.


좋아, 그렇게해야하는 게 이상 하긴하지만 작동하는 것 같다. =)
Ted

0

사용중인 Intent 생성자를 Intent (context, classname)로 변경하고 innerclass에서 getApplicationContext ()를 사용합니다. 어쨌든 내 문제를 해결했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.