Запуск с параметром?
Мне нужен "Runnable, который принимает параметр", хотя я знаю, что такого runnable на самом деле не существует.
Это может указывать на фундаментальный недостаток в дизайне моего приложения и / или умственный блок в моем усталом мозге, поэтому я надеюсь найти здесь несколько советов о том, как сделать что-то вроде следующего, не нарушая фундаментальные принципы ОО:
private Runnable mOneShotTask = new Runnable(String str) {
public void run(String str) {
someFunc(str);
}
};
Любая идея, как сделать что-то подобное выше?
10 ответов
Вы можете объявить класс прямо в методе
void Foo(String str) {
class OneShotTask implements Runnable {
String str;
OneShotTask(String s) { str = s; }
public void run() {
someFunc(str);
}
}
Thread t = new Thread(new OneShotTask(str));
t.start();
}
Вы могли бы поместить это в функцию.
String paramStr = "a parameter";
Runnable myRunnable = createRunnable(paramStr);
private Runnable createRunnable(final String paramStr){
Runnable aRunnable = new Runnable(){
public void run(){
someFunc(paramStr);
}
};
return aRunnable;
}
(Когда я использовал это, моим параметром был целочисленный идентификатор, который я использовал для создания хэш-карты ID -> myRunnables. Таким образом, я могу использовать хэш-карту для публикации / удаления различных объектов myRunnable в обработчике.)
theView.post(new Runnable() {
String str;
@Override
public void run() {
par.Log(str);
}
public Runnable init(String pstr) {
this.str=pstr;
return(this);
}
}.init(str));
Создайте функцию инициализации, которая возвращает сам объект и инициализируйте параметры с ним.
Начиная с Java 8, лучший ответ - использовать Consumer<T>
:
https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html
Это один из функциональных интерфейсов, что означает, что вы можете называть его лямбда-выражением:
void doSomething(Consumer<String> something) {
something.accept("hello!");
}
...
doSomething( (something) -> System.out.println(something) )
...
Я использую следующий класс, который реализует интерфейс Runnable. С помощью этого класса вы можете легко создавать новые темы с аргументами
public abstract class RunnableArg implements Runnable {
Object[] m_args;
public RunnableArg() {
}
public void run(Object... args) {
setArgs(args);
run();
}
public void setArgs(Object... args) {
m_args = args;
}
public int getArgCount() {
return m_args == null ? 0 : m_args.length;
}
public Object[] getArgs() {
return m_args;
}
}
У вас есть два варианта:
Определить именованный класс. Передайте ваш параметр конструктору именованного класса.
Ваш анонимный класс должен быть закрыт по вашему "параметру". Обязательно отметьте это как
final
,
Сначала я хотел бы знать, что вы пытаетесь выполнить, чтобы аргумент передавался в новый Runnable() или run(). Обычным способом должно быть наличие объекта Runnable, который передает данные (str) своим потокам, устанавливая переменные-члены перед запуском. Затем метод run () использует значения переменных-членов для выполнения someFunc().
Пока лучший способ:
Consumer<String> oneShot = str -> {
somefunc(str);
};
oneShot.accept("myString");
/**
* @author AbdelWadoud Rasmi
* <p>
* The goal of this class is to pass some parameters to a runnable instance, a good example is
* after caching a file you need to pass the new path to user to do some work on it.
*/
public abstract class ParameterizedRunnable implements Runnable {
private Object[] params;
/**
* @param params: parameters you want to pass the the runnable.
*/
public ParameterizedRunnable(Object... params) {
this.params = params;
}
/**
* Code you want to run
*
* @param params:parameters you want to pass the the runnable.
*/
protected abstract void run(Object... params);
@Override
public final void run() {
run(params);
}
/**
* setting params
*/
public void setParams(Object... params) {
this.params = params;
}
/**
* getting params
*/
public Object[] getParams() {
return params;
}
}
Создайте новый класс, реализующий Runnable. В этом классе вы можете расширить метод run(), создав абстрактные методы по вашему выбору.
public abstract class CCallback implements Runnable {
@Override
public void run() {}
public abstract void run(Object any);
}
Теперь вы можете использовать этот класс в качестве функции обратного вызова следующим образом:
public void whatever(CCallback callback) {
String any = "any type of param";
if (callback != null)
callback.run(any);
}
Метод «Как угодно» теперь может завершить свою задачу до запуска нашего исполняемого файла:
whatever(new CCallback() {
@Override
public void run(Object any) {
// Here you can reach "any"
}
});