2017-11-28 4 views
1

春の@Asyncのような非同期メソッドをAndroid用に作成するには、アノテーションを作成したいと考えています。私はJavaの注釈プロセッサをチェックしましたが、既存のクラスを変更することはできません(新しいクラスのみを作成できます)。自分の注釈を作成する方法を学習したいので、androidannotationライブラリを使用したくありません。カスタムJavaアノテーションを作成してメソッドを変更する

ロンボクは、クラスを変更することができます(ゲッターとセッターを追加)、我々は、カスタム注釈(https://binkley.blogspot.fr/2014/12/writing-your-own-lombok-annotation.html)を追加することができます

しかし、私はトラブルasynctaskを作成し、メソッドのコードを挿入するために、この例を修正することを持っていることがわかりました。

@Documented 
@Retention(RUNTIME) 
@Target(METHOD) 
public @interface AsyncTask { 
} 

その後、我々は@AsyncTaskためASYNロジックを作成するためにcglibを使用します。>

void doSomething(int a){ 
    new android.os.AsyncTask<Void, Void, Void>() { 
     @Override 
     protected Void doInBackground(Void... voids) { 
      Log.d("here"); 
      return null; 
     } 
    }.execute(); 
} 
+0

クラスを変更し、危険であり、すべてのJVMの維持が必要です。生成されたクラスを作成するか、プロキシを使用するのはどうですか? –

答えて

0

まず、我々は、アノテーションを定義する -

@AsyncTask 
void doSomething(int a){ 
    Log.d("here"); 
} 

あなたの助けをありがとう方法:

import net.sf.cglib.proxy.Enhancer; 
import net.sf.cglib.proxy.MethodInterceptor; 

public class AsyncTaskHandler { 
    @SuppressWarnings("unchecked") 
    public static <T> T handle(T origin) { 
    // collect async methods 
    List<Method> asyncMethods = Arrays.stream(origin.getClass().getMethods()) 
     .filter(m -> m.getAnnotation(AsyncTask.class) != null) 
     .collect(Collectors.toList()); 
    // if no async method, return itself 
    if (asyncMethods.isEmpty()) { 
     return origin; 
    } 
    return (T) Enhancer.create(origin.getClass(), (MethodInterceptor) (obj, method, args, proxy) -> { 
     // if asyn, wrapped in your async code, here I simply create a new thread 
     if (asyncMethods.contains(method)) { 
     // your async logic 
     new Thread(() -> { 
      try { 
      proxy.invoke(origin, args); 
      } catch (Throwable e) { 
      e.printStackTrace(); 
      } 
     }).start(); 
     return null; 
     } 
     return proxy.invoke(origin, args); 
    }); 
    } 
} 

コードをテストしましょう。

public class SomeObject { 

    public static void main(String[] args) { 
    SomeObject so = SomeObject.create(); 
    so.syncDo("1"); 
    so.asyncDo("2"); 
    so.syncDo("3"); 
    so.asyncDo("4"); 
    } 

    public static SomeObject create() { 
    return AsyncTaskHandler.handle(new SomeObject()); 
    } 

    protected SomeObject() {} 

    @AsyncTask 
    public void asyncDo(String who) { 
    System.out.println(who + "\tThread: " + Thread.currentThread()); 
    } 

    public void syncDo(String who) { 
    System.out.println(who + "\tThread: " + Thread.currentThread()); 
    } 
} 

と出力されます:

1 Thread: Thread[main,5,main] 
3 Thread: Thread[main,5,main] 
2 Thread: Thread[Thread-0,5,main] 
5 Thread: Thread[Thread-1,5,main] 
+0

こんにちは あなたの答えはありがとうございますが、パフォーマンス面では、コンパイル時にコードを変更してアノテーションを必要としましたが、実行時には使用しませんでした。だから私はこのメカニズムを使ったロンボクに興味があります。 – kazouz

+0

@kazouz LombokはASTを変更して新しいバイトコードを生成します。維持することは難しいです。既存のコードを変更するのではなく、アノテーション処理で新しいクラスファイルを作成します。 –

関連する問題