我正在设计一个大量使用异步代码完成块的API。
public interface IResult<T extends Result.I> {
void onResult(T);
}
public void doXYZ(IResult<Result.TypeA> iResult) { ... }
用户将调用我的API的doXYZ(),然后单独的网络工作线程将调用iResult.onResult()。有时他并不关心onResult()被调用哪个线程,有时他可能只想更新UI - 只是想找到一种方法来无形地减轻用户的负担,这样他们就可以保留他们的匿名内部类整洁而小巧。
此API适用于Android,其中许多(但不是全部)用户可能希望在影响UI元素的onResult()回调中执行某些操作,因此必须在UI线程上运行其代码。用户不必为使用runOnUIThread(...)调用弄脏代码而负担,我想知道人们是否知道在doXYZ()调用时,设计模式会变得简单,供用户指定是否在其UI线程上调用回调。
出于性能原因,我不要强迫我的API始终在UI线程上调用onResult()。
我见过的一种模式是添加一个方法参数:doXYZ(...,boolean callOnUIThread)。但是,由于API已经过记录,因此我不会通过使用所有这些额外的布尔值来弄脏文档(和方法签名)。
另一个想法是重载每个doXYZ(),有一个有一个没有callOnUIThread参数,但由于膨胀,这对于文档来说非常糟糕。
我的另一个想法是在onResult()之外向IResult添加一个onResultUI()方法,但这会让用户必须始终在匿名中定义这两个代码。类。
有关实现这一目标的干净方法的任何建议: 一世。简洁 II。非常适合代码可读性 III。简单的文档 ?
答案 0 :(得分:2)
为IResult
使用装饰器模式。
E.g。如果你有一个接口IResult
(我只是让演示的通用类型T更容易)
interface IResult<T> {
void onResult(T result);
}
和像这样的结果回调实现
class PrintCurrentThreadAndResult implements IResult<String> {
@Override
public void onResult(String result) {
Thread thread = Thread.currentThread();
System.out.print(thread.getName());
System.out.print(" - ");
System.out.println(result);
}
}
你可以创建一个装饰器,确保在特殊线程(例如ui线程)上调用装饰结果。我在这里使用swing的事件调度程序线程,这样每个人都可以轻松地编译和测试它。
class UIThreadAwareResult<T> implements IResult<T> {
private IResult<T> delegate;
public UIThreadAwareResult(IResult<T> delegate) {
this.delegate = delegate;
}
@Override
public void onResult(T result) {
invokeOnUIThread(result);
}
private void invokeOnUIThread(final T result) {
try {
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
delegate.onResult(result);
}
});
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
客户端代码然后可以通过装饰原始结果来选择要运行的线程。
public class Main {
public static void main(String[] args) {
Main main = new Main();
IResult<String> result = new PrintCurrentThreadAndResult();
main.doXYZ(result);
IResult<String> uiThreadAwareResult = new UIThreadAwareResult<String>(result);
main.doXYZ(uiThreadAwareResult);
}
public void doXYZ(IResult<String> iResult) {
iResult.onResult("Hello");
}
}
输出
main - Hello
AWT-EventQueue-0 - Hello