Skip to content
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
This repository was archived by the owner on Feb 26, 2023. It is now read-only.

Implement a generalized way to handle Event Binding #2219

@smaugho

Description

@smaugho

Event binding in AA right now is limited to some specific View Listeners, let's say @Click, @OnLongClick, or similar.

Even if all those annotations are quire similar, it is mandatory to create a new annotation handler for each one of them, and basically change AA (or create a plugin) to support others.

But creating a generalization of this mechanism is not that complicated. I would like to suggest a solution which could serve to generalize the implementation of these methods.

Firstly, a generic @ViewEvent annotation should be created, which looks as follow:

@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface ViewEvent {

    /**
     * The R.id.* fields which refer to the Views.
     *
     * @return the ids of the Views
     */
    int[] value() default {};

    /**
     * The resource names as strings which refer to the Views.
     *
     * @return the resource names of the Views
     */
    String[] resName() default {};

     /**
     * Class which contains the listener provided
     *
     * @return the listener holder class name
     */
    String listenerHolderView();

     /**
     * Listener which will be used to bind the annotated method.
     *
     * @return the listener method name
     */
    String listener();

     /**
     * Suffixes which could be used to name the methods
     *
     * @return valid suffix for the methods
     */   
    String[] validSuffix() default {};

}

The idea of creating this @ViewEvent annotation is not to be used directly, but there is no issue if the programmer wants to use it directly. But the biggest advantage is to be able to create a new annotation from it, which will be processed by AA. I'll add example of two annotations, @Click and @LongClick:

@ViewEvent(listenerHolderView="android.view.View", listener = "setOnClickListener", validSuffix = {"Click", "Clicked", "Tap", "Tapped"})
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface Click {

    /**
     * The R.id.* fields which refer to the Views.
     *
     * @return the ids of the Views
     */
    int[] value() default ResId.DEFAULT_VALUE;

    /**
     * The resource names as strings which refer to the Views.
     *
     * @return the resource names of the Views
     */
    String[] resName() default {};

}

@ViewEvent(listenerHolderView="android.view.View", listener = "setOnLongClickListener -> return true;", validSuffix = {"LongClick", "LongClicked", "LongTap", "LongTapped"})
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface LongClick {

    /**
     * The R.id.* fields which refer to the Views.
     *
     * @return the ids of the Views
     */
    int[] value() default ResId.DEFAULT_VALUE;

    /**
     * The resource names as strings which refer to the Views.
     *
     * @return the resource names of the Views
     */
    String[] resName() default {};

}

Now, the validation and the processing of the annotation should be done by the holder annotation, so any ComponentWithViewSupport annotation, will check its method to look for any annotation which is annotated with @ViewEvent, and it will execute:

  • validations based on the parameters of the provided listener
  • bind the view based on the provided listener.

The process is not really that complicated, since given the listenerHolderView you can access to the method via its TypeElement, detect the parameters and validate them. The interface for it is also fully generated.

I see many advantages of this approach:

  • It permits developers to add other listeners if they need to, since the annotations are easily created.
  • It is fully compatible with the existing annotations, AA will simply provide some implementations for all the current annotations provided by the framework (@Click, @LongClick, ....)

I was already "playing" with some implementation for this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions