1

dex形式で使用する予定のライブラリがあります。このライブラリに対して直接コンパイルしたいのですが、エクスポートはしたくありません。代わりに、リソースにドロップし、クラスローダーを使用して実際にインスタンス化したいと考えています。

だからここに私のライブラリがあります:

public class Foo {
  public doFoo(String message) {
  }

  public doFoo(int count, String message) {
  }
}

今私は電話したいdoFoo()。多くの。リフレクションを使用するのがおそらく合理的ではありません。現在、以下で動作します:

public class FooConsumer {
  private final DexClassLoader fooLoader;

  public FooConsumer(DexClassLoader fooLoader) {
    this.fooLoader = fooLoader;
  }

  public void go() {
    Class<?> fooClass = fooLoader.loadClass("com.library.Foo");
    Object fooInstance = fooClass.newInstance();
    Method fooMethodDoFoo = fooClass.getMethod("doFoo", String.class);
    fooMethodDoFoo.invoke(fooInstance, "Hello World");
  }

これは明らかに醜いです。特に例外処理を含めていないため、そこにはキャッチするスロー可能なオブジェクトが 6 つあるためです。たくさんのものをキャッシュすることができ、速度が少し向上しましたが、それほど多くはありませんでした。

通常、インターフェイスを持つ 3 番目のライブラリを両方とも認識していますが、ライブラリにはいくつかの静的メソッドがあり、とにかく編集できません。次のようなことができれば本当にいいです:

public class FooConsumer {
  private FooAccessor accessor;

  public FooConsumer(DexClassLoader fooLoader) {
    Object fooInstance = fooLoader.loadClass("com.library.Foo").newInstance();
    Log.i("TEST", "fooInstance: " + fooInstance);
    this.accessor = new FooAccessor(fooInstance);
  }

  public void go() {
    accessor.doFoo("Hello World");
  }

  private static class FooAccessor {
    private Foo fooInstance;

    public FooAccessor(Object instance) {
      fooInstance = (Foo)instance;
    }

    public void doFoo(String message) {
      fooInstance.doFoo(message);
    }
  }
}

私がそこで何をしたか見てください。内部クラスは Foo オブジェクトの単なるラッパーです。私はそれに対してリンクしましたが、エクスポートしていません。すべてがうまくいっています。しかし、うまくいきません。logcatで私は得る

I/TEST: fooInstance: com.library.Foo@413b1b68
E/AndroidRuntime: java.lang.NoClassDefFoundError: com.library.Foo
  ...

渡したクラスローダーを FooAccessor に使用させる方法はありますか? それとも、クラスローダーの使用はリフレクション地獄への地獄ですか。

4

1 に答える 1