Android開発のコンポーネント化におけるAPTの使用

APTとは何ですか?

APT(注釈処理ツール)

注釈を処理するためのツールであり、ソースコードファイル内の注釈を検出し、注釈に基づいてコードを自動的に生成します。カスタム注釈プロセッサを正常に実行する場合は、APTツールを使用して処理する必要があります。また、APTツールが宣言された後にのみ、プログラムのコンパイル中にカスタム注釈インタープリターを実行できることも理解できます。

一般的な理解:ルールに従って、コードの生成とクラスファイルの生成を支援する

Android Studio 3.4.1 + Gradle5.1.1(推奨バージョン)

コンポーネント化でAPTを使用する方法は?

コンポーネント開発は、デカップリングと高度な分離のためのものです。各モジュールは独立しています。各コンポーネントの直接的な相互作用を実現したい場合は、次の方法を使用できます。

  • リフレクションリフレクションテクノロジーは成功する可能性があり、メンテナンスコストが高く、高いバージョンの@hide制限が表示される傾向があります
  • 多くのEvenTBusEventBeans(1対1)があり、1対多は面倒で保守が困難です(私はこれを試していません)
  • 暗黙のインテントメンテナンスのコストは問題ありませんが、それはより面倒であり、マニフェストで維持するには多すぎるアクションが必要です
  • BroadCastReceiverには動的登録(7.0以降)が必要であり、困窮している当事者がブロードキャストを送信します
  • クラスの読み込みには完全なクラス名への正確なパスが必要であり、元のバージョンのメンテナンスは比較的高く、人為的なエラーが発生しやすい

次に、主にAPTがコンポーネント開発における相互作用の最良のソリューションの1つであると言って、多くのことを言います。

それで、それをどのように使用するのですか?

まず、例としてさまざまなコンポーネント間のインターフェイスジャンプを取り上げます。

メインページモジュール(MainActivity)と注文モジュール(OrderActivity)の間のインターフェイスジャンプ:

1つは、新しい注釈クラスを作成する

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)//RetentionPolicy.CLASS 编译期预编译的操作
public @interface ARouter {

    //详细路由器路径(必填),如:"/app/MainActivity"
    String path();

    // 从path中截取出来
    String group() default "";
}

2.新しいARouterProcessorを作成して、AbstractProcessorを継承し、注釈作業を実装します

ARouterProcessorはAbstractProcessorを継承し、ARouterアノテーションのあるクラスに、コンパイル中にインタラクティブに使用するための新しいクラスが生成されます。


@AutoService(Processor.class)
@SupportedAnnotationTypes("com.goodboy.annotation.ARouter")
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedOptions("content")
public class ARouterProcessor extends AbstractProcessor {

    //操作Element工具类
    private Elements elementUtils;

    //type(类信息)工具类
    private Types typeUtils;

    //用来输出警告,错误等日志
    private Messager messager;

    //文件生成器
    private Filer filer;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
        elementUtils = processingEnvironment.getElementUtils();
        typeUtils = processingEnvironment.getTypeUtils();
        messager = processingEnvironment.getMessager();
        filer = processingEnvironment.getFiler();

        String content = processingEnvironment.getOptions().get("content");
        messager.printMessage(Diagnostic.Kind.NOTE,content);
    }

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        if (set.isEmpty())return false;

        //获取项目中所有使用使用了ARouter注解的节点
        Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(ARouter.class);
        //遍历所有的类节点
        for (Element element : elements) {
            //类节点之上,就是包节点
            String packageName = elementUtils.getPackageOf(element).getQualifiedName().toString();
            //获取简单类名
            String className = element.getSimpleName().toString();
            messager.printMessage(Diagnostic.Kind.NOTE,"被注解的类有:" + className);
            // 最终我们想要生成的类文件 如:MainActivity$$ARouter
            String finalClassName = className + "$$ARouter";
            // 公开课写法,也是EventBus写法(https://github.com/greenrobot/EventBus)
            try {
                // 创建一个新的源文件(Class),并返回一个对象以允许写入它
                JavaFileObject sourceFile = filer.createSourceFile(packageName + "." + finalClassName);
                // 定义Writer对象,开启写入
                Writer writer = sourceFile.openWriter();
                // 设置包名
                writer.write("package " + packageName + ";\n");

                writer.write("public class " + finalClassName + " {\n");

                writer.write("public static Class<?> findTargetClass(String path) {\n");

                // 获取类之上@ARouter注解的path值
                ARouter aRouter = element.getAnnotation(ARouter.class);

                writer.write("if (path.equals(\"" + aRouter.path() + "\")) {\n");

                writer.write("return " + className + ".class;\n}\n");

                writer.write("return null;\n");

                writer.write("}\n}");

                // 最后结束别忘了
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return true;
    }
}

3.この注釈をMainActivityクラスとOrderActivityクラスに追加し、生成されたクラスを使用して
MainActivityコードにジャンプします。

@ARouter(path = "/app/MainActivity")
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }


    public void jump(View view){
        Class<?> targetClass = OrderActivity$$ARouter.findTargetClass("/app/OrderActivity");
        startActivity(new Intent(this, targetClass));
    }
}

OrderActivityコード


@ARouter(path = "/app/OrderActivity")
public class OrderActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_order);
        Log.d("mile", "--->OrderActivity");
    }

    public void jump(View view) {
        Class<?> targetClass = MainActivity$$ARouter.findTargetClass("/app/MainActivity");
        startActivity(new Intent(this, targetClass));
    }
}

概要:コンポーネント開発では、APTを動的に使用して相互運用可能なクラスを生成します

おすすめ

転載: blog.csdn.net/yanwenyuan0304/article/details/106020717