2012-02-03 6 views
33

У меня есть поток, который использует обработчик для отправки экземпляра runnable. он работает хорошо, но мне любопытно, как я буду передавать параметры, которые будут использоваться в экземпляре Runnable? Возможно, я просто не понимаю, как работает эта функция.Есть ли способ передать параметры Runnable?

Чтобы упредить вопрос «зачем вам этот вопрос», у меня есть многопоточная анимация, которая должна перезвонить в поток пользовательского интерфейса, чтобы рассказать ей, что на самом деле делать.

ответ

67

Просто класс, который реализует Runnable с конструктором, который принимает параметр может сделать,

public class MyRunnable implements Runnable { 
    private Data data; 
    public MyRunnable(Data _data) { 
    this.data = _data; 
    } 

    @override 
    public void run() { 
    ... 
    } 
} 

Вы можете просто создать экземпляр класса Runnable с параметризированным конструктором.

MyRunnable obj = new MyRunnable(data); 
handler.post(obj); 
+2

Мне нравится этот подход, но как мне общаться с этим классом изнутри моего потока таймера (Runnable отсутствует в основном потоке пользовательского интерфейса). Могу ли я просто сделать его общедоступным и установить его в моем потоке таймера до передачи Runnable в обработчик? Кажется слишком хорошим, чтобы быть правдой :) –

+0

Извините, что ответил поздно, отредактировал мой ответ. –

+0

По какой-то причине я думал, что если obj создается какое-то место, кроме потока пользовательского интерфейса, то при попытке манипулировать представлением (в основном потоке) приложение будет аварийно завершено. Большое спасибо. –

8

Есть различные способы сделать это, но самый простой заключается в следующем:

final int param1 = value1; 
final int param2 = value2; 
... new Runnable() { 
    public void run() { 
     // use param1 and param2 here 
    } 
} 
+0

Я предполагаю, что я должен уточнить, что я хотел бы избежать использования глобального Params в моем классе, таким образом, ... :) Спасибо, но я действительно пытаюсь получить метод для передачи аргументов или использования какой-либо другой конструкции, которая их принимает (если Runnable не делает) –

+0

Вы можете сохранить их как поля в Runnable, но это о ней , Вы также можете использовать Callable. –

+0

Это вызовет проблему синхронизации при вызове второго сообщения до того, как первое сообщение будет обработано Runnable. – marcelnijman

6

Если вам нужно передать информацию в Runnable, вы можете всегда иметь конструктор Runnable объекта принять эту информацию, или может имеют другие методы на Runnable, которые позволяют получить эту информацию, или (если Runnable является анонимным внутренним классом) могут объявлять соответствующие значения final, чтобы Runnable мог получить к ним доступ.

Надеюсь, это поможет!

+0

Будет ли Callable быть в порядке с запуском из потока, который не является потоком пользовательского интерфейса? Причина, по которой я делаю это для начала, заключается в том, что вы не можете просто обратиться к основному потоку в Android, если собираетесь изменить какие-либо элементы пользовательского интерфейса. –

+0

@ Dr.Dredel- Да, любой поток должен иметь возможность запускать Callable. – templatetypedef

+0

+1 для использования анонимного класса, расширяющего 'Runnable' и ссылающийся на' final' переменные, если только он используется только в одном месте –

1

Хотя вы можете использовать любой из указанных выше ответа, но если вопрос действительно обеспокоен Android, то вы можете также использовать AsyncTask.

+0

AsyncTask может манипулировать представлениями в потоке пользовательского интерфейса (я понимаю, что это относится только к Android)? –

-1

Я думаю, что нашел более простой подход:

public interface MyRunnable extends Runnable { 
    public void run(int data); 
} 

public void someMethod(int n, String s, MyRunnable r) { 
    ... 
    r.run(n); 
    ... 
} 

вызов:

someMethod(5, "Hello", new MyRunnable() { 

    @Override 
    public void run(int data) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void run() { 
     // TODO Auto-generated method stub 

    } 
}); 
+0

За исключением того, что 'MyRunnable' не расширяет« Runnable », поэтому вы не сможете использовать его там, где ожидается« Runnable ». – assylias

+0

@assylias Интерфейс может расширяться при необходимости. – ilomambo

+0

Да, но это не проблема. Обычно вы вызываете 'новый поток (новый MyRunnable() {...});', но это вызовет метод 'run()', а не метод 'run (int data);'. Если у вас есть метод 'run', вызывается метод' run (int data) ', но как вы передаете параметры? Попробуйте использовать свое предложение с помощью реального примера, и вы увидите проблемы. – assylias

Смежные вопросы