Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Custom Annotation Preprocessor — создание на базе Android-приложения и конфигурация в IntelliJ IDEA

Anna | 4.06.2014 | нет комментариев
Всем здравствуй!

Незадолго передо мною встала задача написания своих кастомных аннотации и их обработки во время компиляции. 1-й вопрос, тот, что я себе задала: с чего начать? Позже обзора я решила поделиться с вами результатом на данный вопрос.
Думаю, рассказывать, что такое аннотации в java и с чем их едят, не имеет смысла, так как всякому юному программисту это знакомо ( а кому не знакомо, может прочесть самосильно). К тому же на прогре есть увлекательная ознакомительная статья об этом явлении.
Но сегодня я хочу побеседовать именно о кастомных аннотациях в Android-приложении, которые обрабатываются в процессе компиляции плана вашим собственным обработчиком и о автогенерации классов на их основе. А так же, по ходу дела, расскажу вам, как стремительно все настроить в IDEA (сама я пользуюсь версией 12.1, допустимо в других есть различия).

Для реализации нам потребуется 2 плана: в первом опишем наши кастомные аннотации и их обработчик, из него сгенерируем jar файл, тот, что подключим ко второму тестовому плану, тот, что и будет применять наши аннотации.

Шаг 1

Создаем новейший library план, в котором описываем свою аннотацию. Класс с аннотацией выглядит приблизительно так:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface CustomAnnotation {

    String className();
    String value() default "Hello";
    int type() default 0;
}

@Retention говорит о том, что наша аннотация будет присутствовать только в начальном коде и отброшена компилятором (а до этого момента мы её обработаем).

Шаг 2

Создаем непринужденно наш обработчик аннотаций. Он представляет собой класс, расширяющий AbstractProcessor. Ему мы говорим, что он будет обрабатывать все аннотации и указываем поддерживаемую версию начальных файлов таким образом:

@SupportedAnnotationTypes({"*"})
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class CustomProcessor extends AbstractProcessor { 
}

Дальше переопределяем способ process, в котором прописываем логику генерации нового класса. Мой способ выглядит так:

@Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {

        for (Element e : roundEnv.getElementsAnnotatedWith(CustomAnnotation.class)) {
            CustomAnnotation ca = e.getAnnotation(CustomAnnotation.class);
            String name = e.getSimpleName().toString();
            char[] c = name.toCharArray();
            c[0] = Character.toUpperCase(c[0]);
            name = new String(name);
            TypeElement clazz = (TypeElement) e.getEnclosingElement();
            try {
                JavaFileObject f = processingEnv.getFiler().
                        createSourceFile(clazz.getQualifiedName()   "Autogenerate");
                processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,
                        "Creating "   f.toUri());
                Writer w = f.openWriter();
                try {
                    String pack = clazz.getQualifiedName().toString();
                    PrintWriter pw = new PrintWriter(w);
                    pw.println("package "
                              pack.substring(0, pack.lastIndexOf('.'))   ";");
                    pw.println("npublic class "
                              clazz.getSimpleName()   "Autogenerate {");

                    TypeMirror type = e.asType();

                    pw.println("n    public "   ca.className()   " result = ""   ca.value()   "";");

                    pw.println("    public int type = "   ca.type()   ";");

                    pw.println("n    protected "   clazz.getSimpleName()
                              "Autogenerate() {}");
                    pw.println("n    /** Handle something. */");
                    pw.println("    protected final void handle"   name
                              "("   ca.className()   " value"   ") {");
                    pw.println("n//"   e);
                    pw.println("//"   ca);
                    pw.println("n        System.out.println(value);");
                    pw.println("    }");
                    pw.println("}");
                    pw.flush();
                } finally {
                    w.close();
                }
            } catch (IOException x) {
                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
                        x.toString());
            }
        }
        return true;
    }

На этом этапе дозволено включить фантазию и писать, что душе желательно (ну либо что требуется =). Позже того, как вы завершили с обработчиком аннотаций и описали все свои кастомные аннотации, из этого плана необходимо сгенерировать jar файл. В Idea 12 это делается довольно легко: Project Settings -> Artifacts -> Add -> Jar -> From modules… Дальше делаем Build -> Rebuild Project и находит наш сгенерированный файл jar в Output директории плана.

Шаг 3

Создаем тестовый план, в котором и будем применять наши кастомные аннотации. К плану подключаем сгенерированный на прошлом шаге jar файл и радуемся, что наши аннотации сейчас нам доступны. В любом классе прописываем нашу аннотацию, скажем так:

public class MyActivity extends Activity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @CustomAnnotation(className = "String", type = 1)
    public void annotatedMethod(String value) {
    }
}

Помните, что мы указали нашей аннотации @Target(ElementType.METHOD), а это значит что мы можем прописать ее только перед способом.

Шаг 4

Сейчас скажем Idea применять наш обработчик аннотаций и магия начнет трудиться! Для этого идём вSettings в раздел Compiler — > Annotation Processors. Ставим галочку Enable annotation processing, в поле Processor path указываем путь к нашему сгенерированному jar файлу. Так же в окне Processor FQ name вводим полное наименование класса, тот, что отвечает за обработку. В нашем случает это CustomProcessor. Заполненное окно должно выглядеть приблизительно так.

Шаг 5

Делаем Build -> Rebuild project и наслаждаемся итогами. В дереве плана должна возникнуть папка generated, в которой будут лежать новые файлы.
Вот что получилось у меня:

public class MyActivityAutogenerate {

    public String result = "Hello";
    public int type = 1;

    protected MyActivityAutogenerate() {}

    /** Handle something. */
    protected final void handleannotatedMethod(String value) {

//annotatedMethod(java.lang.String)
//@com.example.AnnotationsProcessor.CustomAnnotation(type=1, value=Hello, className=String)

        System.out.println(value);
    }
}

Happy codding!

Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB