Как да променя външната променлива от анонимен вътрешен клас?

Имам локална променлива във външния си метод, която искам да променя от анонимен вътрешен клас. Как мога да го направя?

Опитах решението, използвайки масив от един елемент, описан тук

public class outerClass{
    static public void outerMethod(Interface interface) {
        final String[] variable = new String[1];
        new Thread(new Runnable() {
            @Override
            public void run() {
                variable[0] = "Hello";
                Log.i("test", variable[0]); // Works, prints "Hello"
            }
        }).start();
        Log.i("test", variable[0]); // Doesn't work, null string
    }
}

и решението с помощта на държач, описано тук

public class outerClass{
    static public void outerMethod(Interface interface) {
        final Holder<String> variable = new Holder<String>;
        new Thread(new Runnable() {
            @Override
            public void run() {
                variable.held = "Hello";
                Log.i("test", variable.held); // Works, prints "Hello"
            }
        }).start();
        Log.i("test", variable.held); // Doesn't work, null string
    }
}

class Holder<String> {
    public String held;
}

но и двете не работят в моя случай по някаква причина.

Може да е уместно, но различното е, че моят външен метод е статичен. Тук също опростих кода си, оригиналният код беше за анонимен клас за обратно извикване от библиотеката Retrofit на Android.


person J. Doe    schedule 06.02.2016    source източник
comment
Създавате ли и стартирате ли Thread, за да управлявате своя Runnable?   -  person rgettman    schedule 06.02.2016


Отговори (2)


Създавате клас Runnable, но той всъщност никога не се изпълнява. Трябва да го "стартирате", като извикате метода му start().

Но трябва също така да имате предвид, че когато го стартирате вътре в outerMethod(), той може да не се изпълни, преди да бъде извикан методът Log (тъй като ще се изпълнява в отделна нишка) и редът, в който се извиква кодът, не е гарантирано вече.

person radoh    schedule 06.02.2016
comment
Това не е истинският ми код, опростих го, така че забравих да сложа началото. Ако всичко изглежда наред, искате ли вместо това да поставя действителния код? - person J. Doe; 06.02.2016
comment
Редактирах отговора си за допълнителен коментар относно нишките и реда, в който се изпълнява последващият код. - person radoh; 06.02.2016
comment
Благодаря ви много, това наистина беше проблемът! Регистърът е стартиран преди нишката да промени променливата. Добавих join() към нишката, за да изчакам, докато приключи, за да отпечатам журнала, и това вече работи като чар! - person J. Doe; 06.02.2016

Проверете синхронизирането на вашите нишки. Използвайте Object.wait() или синхронизирана ключова дума. Вашата основна нишка не чака, докато новата създадена нишка инициализира променлива. Трябва да изчака това да приключи.

И между другото вашият клас не може да бъде вътрешен клас. Вижте тук

person Anton Astafiev    schedule 06.02.2016