LoginSignup
5
6

More than 5 years have passed since last update.

Androidでメソッド数を増やさずにlambdaを実装する方法

Posted at

ProxyInvokationHandlerをつかうと都度クラスを定義することなくSAMから特定のメソッドへの移譲を実現できます。

欠点はめちゃくちゃ遅いこと! ふつうに new Runnable() { ... } するのにくらべて数百倍遅いです。

もうちょっと速ければ、RetroLambdaやJackの内部実装のオプションとして使うのもありかもしれないとおもっ検証してみたのですが、これはちょっと使いものにならなそうです。メソッド数を増やさないというのはそれなりには重要ですが、multidexがある今となってはそこまで優先すべきものでもないですし。

実装

たとえばこんなクラスを定義します。

public class InvocationDelegator<T> implements InvocationHandler {

    final T receiver;

    final Method delegate;

    public static <U, F> F create(U receiver, Class<F> samClass, String delegate) {
        for (Method method : samClass.getMethods()) {
            if (Modifier.isAbstract(method.getModifiers())) {
                Class<?>[] interfaces = {samClass};
                InvocationHandler handler = new InvocationDelegator<>(receiver, delegate, method.getParameterTypes());
                return samClass.cast(Proxy.newProxyInstance(samClass.getClassLoader(), interfaces, handler));
            }
        }
        throw new RuntimeException("No method found in " + samClass.getCanonicalName());
    }

    public InvocationDelegator(T receiver, String delegate, Class<?>[] parameterTypes) {
        this.receiver = receiver;

        try {
            this.delegate = receiver.getClass().getDeclaredMethod(delegate, parameterTypes);
            this.delegate.setAccessible(true);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException("Missing " + delegate + "() in " + receiver.getClass().getCanonicalName(), e);
        }
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       return delegate.invoke(receiver, args);
    }
}

MainActivityに以下のメソッドがあるとして:

private void doSomething() {
    Log.d("XXX", "Hello, world!");
}

これで doSomething() を呼び出すRunnableを生成できます。

Runnable task = InvocationDelegator.create(this, Runnable.class, "doSomething");
task.run(); // this.doSomething() を呼び出す
5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6