Усередині 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.

Я міг би робити статичне посилання зовні і використовувати його всередині, але це правильно? Здається дивним, що доводиться це робити постійно?

Відповіді:


231

Замініть thisу своєму коді MyActivity.thisде MyActivity - це назва класу вашого підкласу Activity.

Пояснення: Ви створюєте анонімний внутрішній клас, коли використовуєте цю частину коду:
new OnClickListener() {
Анонімні внутрішні класи мають посилання на екземпляр класу, в якому вони створені. Схоже, ви створюєте його всередині підкласу Activity, оскільки findViewById є Метод діяльності. Діяльність - це контекст, тому все, що вам потрібно зробити, це використовувати посилання на них, яке ви маєте автоматично.


1
Я якийсь час гуглив, щоб просто знайти "MyActivity.this". Зараз це здається так просто. Дякую за інформацію!
TCCV

А як щодо доступу до змінних, які дають помилку Cannot refer to a non-final variable table inside an inner class defined in a different method? Я не можу отримати доступ до них через MyActivity.this.
Майкл

Це місцеві змінні. Якщо вони не зміняться, ви можете змінити їх декларацію, щоб вони мали остаточне значення. Якщо вони все-таки змінюються, але до того, як визначений ваш внутрішній клас, ви можете просто визначити остаточну версію безпосередньо перед цим. Наприклад: final int myFinalErrorCode = errorCode. В іншому випадку вам доведеться зробити щось на зразок зробити і встановити учасника для активності, до якої ви маєте доступ, або у внутрішньому класі.
Lance Nanek

Я не розумію, що це поводиться, але це працює, як ви сказали Activity.this.doStg(). Чи можете ви долучити сюди @LanceNanek якусь URL-адресу з більш докладним поясненням, будь ласка. Це якось пов’язано з реактивним програмуванням?
murt

Див. Приклад "ShadowTest.this" тут: docs.oracle.com/javase/tutorial/java/javaOO/nested.html
Ленс Нанек,

10

Ви також можете застосувати інтерфейс OnClickListener у своєму класі та уникнути потреби в анонімному внутрішньому класі. Тоді ви встановите слухач при натисканні так:

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

Якщо у вас кілька кнопок з одним прослуховувачем, ви можете використовувати оператор switch із view.getId () (що відповідає ідентифікатору подання в R.id), щоб розрізнити їх.


4

Є кілька речей, які ви можете зробити, ви можете створити внутрішній клас, який реалізує onClickListener, і передати необхідні аргументи в конструктор класу. Я досі не вважаю цього найчистішим підходом. Зазвичай я просто створюю інший метод для здійснення своєї дії. Тож у onClick (View v) я б зробив щось подібне.

onClick(View v){doMyAction(myParams)}

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

І просто передайте необхідні параметри від методу слухача до методу поза слухачем.


Гаразд, дивно, що так треба робити, але, мабуть, це працює. =)
Тед,

0

Змініть використовуваний конструктор Intent на Intent (контекст, ім'я класу) і використовуйте getApplicationContext () у своєму внутрішньому класі. У будь-якому разі вирішив мою проблему.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.