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.

Order of calling @AfterViews annotated methods from super classes  #810

Description

@AntekM

I have such inheritance hierarchy:
A -> B -> C (both A and B are abstract activities/fragments).
All classes have methods with @Afterviews annotations - lets say initA, initB and initC

What I have noticed, if I just compile project (I'm using AndroidStudio, but as I remember I had similar problem in Eclipse), after changing something in class B, methods will be called in order:
initB, initA, initC
After clean rebuild i get the correct order:
initA, initB, initC - until I change again something in B

I think they should always be called in order consistent with inheritance hierarchy, otherwise it causes lots of unexpected bugs if i forget to do clean rebuild

Activity

  1. WonderCsabo commented on Dec 26, 2013

    @WonderCsabo
    Member

    You should not rely on the generation order at all! This is what i do for make sure the order is correct:

    @EActivity
    public class Parent extends Activity {
    
        @AfterViews
        protected void afterViews() {
            // do here something related to parent
        }
    }
    @EActivity
    public class Child extends Parent {
    
        @Override // no @AfterViews !
        protected void afterViews() {
            super.afterViews(); // does something related to parent
            // do here something related to child
        }
    }
  2. DayS commented on Jan 10, 2014

    @DayS
    Contributor

    I think the problem here is incremental build. We can't know in which order classes will be processed. As we add @AfterInit/@AfterInject methods calls in the generated class each time we hit a method annotated with this, the order isn't guaranteed.

    However, we really should find a way to fix this. I'm planning this for 3.1.

  3. AntekM commented on Jan 10, 2014

    @AntekM
    Author

    Cool. That would be great, especially with Android Studio gaining more
    traction.

    I found some way around it, but as with every way around it's not perfect ;)

    On Fri, Jan 10, 2014 at 6:00 PM, Damien notifications@github.com wrote:

    I think the problem here is incremental build. We can't know in which
    order classes will be processed. As we add @AfterInit/@AfterInjectmethods calls in the generated class each time we hit a method annotated
    with this, the order isn't guaranteed.

    However, we really should find a way to fix this. I'm planning this for
    3.1.

    —
    Reply to this email directly or view it on GitHubhttps://github.com//issues/810#issuecomment-32015187
    .

    Pozdrawiam / Greetings,
    Antoni Mysliborski
    http://mysliborski.com/blog

  4. bperin commented on Jan 30, 2014

    @bperin

    I ran into this same problem and it took me forever to figure out what was going on, good fix @WonderCsabo

  5. dodgex commented on Aug 29, 2014

    @dodgex
    Member

    @WonderCsabo @yDelouis @DayS

    What about a priority system? you define a priority on the @AfterXXX annotation.

    • default priority is 0
    • a higher priority value results in an earlier call
    • if two or more methods have the same priority, the call order is random (as it is now)

    e.g.

    @EActivity
    public class Parent extends Activity {
    
        @AfterViews(priority=10)
        protected void parent10() {
            // do here something related to parent
        }
        @AfterViews(priority=20)
        protected void parent20() {
            // do here something related to parent
        }
    
        @AfterViews(priority=0) // 0 = default
        protected void parent0() {
            // do here something related to parent
        }
    }
    @EActivity
    public class Child extends Parent {
    
        @AfterViews(priority = 5)
        protected void child5() {
        }
    
        @AfterViews(priority = 10)
        protected void child10() {
        }
    
        @AfterViews(priority = 15)
        protected void child15() {
        }
    
        @AfterViews(priority=0) // 0 = default
        protected void child0() {
            // do here something related to parent
        }
    }

    call order:

    parent20();
    child15();
    child10(); // random order here!
    parent10(); // random order here!
    child5();
    parent0(); // random order here!
    child0(); // random order here!

    while i'm sure that this is possible, i'm not sure how much work it is for current AA implementation of code generation. i tried to understand what happens after proccessing but for the short time i had to dig in the code i was not able to understand it. ;)

    my current theory (correct me if i'm wrong) the generating part of AA at some point calls BaseGeneratedClassHolder.getGeneratedClass() and writes the code to a file.

    i think we could add the @AfterXXX not directly to a method body/block but to a list of calls or better a map of list like Map<Integer, List<JInvocation>> and before getting the generated class for source generation we have a nowAddAllTheCallsToThierCorrectPosition() that adds the calls from that map to thier corresponding method body/block.

    thoughts?

  6. WonderCsabo commented on Aug 29, 2014

    @WonderCsabo
    Member

    Actually i am not really sure we should handle this. My comment solves this in the plain old inheritance way, which is more cleaner than your proposal, also does not let the user to totally ignore the class hiearchy.

  7. dodgex commented on Aug 29, 2014

    @dodgex
    Member

    and an alternative way to handle the priority value (in this case maybe with a diffrent name)

    • default priority is somewhere > 0 (100 or 1000?)
    • a higher priority value results in a later call call
    • if two or more methods have the same priority, the call order is random (as it is now)

    the example from above would result in an order like this

    parent0(); // random order here!
    child0(); // random order here!
    child5();
    child10(); // random order here!
    parent10(); // random order here!
    child15();
    parent20();

    while writing the previous comment i thought that this order feels a bit better

    and i think this way it is easier to have something like
    priority levels 100, 200, 300 with one method each in the parent class. here you can say in what order these methods have to be called to correctly work for the parent classes and child classes have enough priority levels in between to call methods before and/or after a certain parent method.

  8. dodgex commented on Aug 29, 2014

    @dodgex
    Member

    @WonderCsabo i can understand your point

    and although i'm 100% not sure if this is really needed i still think that there could be some use cases where this could be usefull.

    But well, my job here is not to decide what to implement (and how). i'm here to suggest what could be done and maybe write some code to get it done.

    I just gave this issue some brain time as @DayS said

    However, we really should find a way to fix this. I'm planning this for 3.1.

  9. WonderCsabo commented on Aug 29, 2014

    @WonderCsabo
    Member

    No worries, thanks for sharing all your thoughts here, ideas are always welcomed. I have several problems with this issue:

    • i do not really like the possibilities how can we fix this
    • we already can use it as i illustrated, and that method is quiet clean
    • reordering implementation can be really hard, since in incremental compilation we can only access the current class... Also to implement this we should alter the architecture of AA.

    @yDelouis ?

  10. yDelouis commented on Aug 29, 2014

    @yDelouis
    Contributor

    This solution makes the annotation complicated because we have to know what the value of the priority in the annotated methods in the hierarchy.
    AA is made to make code cleaner, not to complicate it.
    Then, it's not written that we guaranty any order. (Maybe we should write in the wiki that the order is random).
    Finally, the example given by @WonderCsabo has a clean code and solve this problem so we shouldn't provide anything else.

    One thing we maybe should do is, in the example given by @WonderCsabo, if the method afterViews of Child is annotated with @AfterViews, we generate only one call to afterViews() in the generated class (actually we generate two calls).

  11. dodgex commented on Aug 29, 2014

    @dodgex
    Member

    Okay. This looks like a decision.

    I suggest to close this issue with a wontfix label and create a new issue to update the wiki to explicitly mention that all three @AfterXXX annotations do not guarantee an calling order beside thier actually when to call rules like @AfterInject once after the @Bean etc stuff got injected.

    also there should be an issue for the two calls that get generated as @yDelouis mentioned

  12. WonderCsabo commented on Aug 29, 2014

    @WonderCsabo
    Member

    BTW in incremental compilation do we access properties of the superclass?

  13. modified the milestones: 3.1, 3.2 on Sep 20, 2014
  14. removed this from the 3.2 milestone on Sep 22, 2014
  15. WonderCsabo commented on Sep 22, 2014

    @WonderCsabo
    Member

    This is a wonftix. The doc should be updated though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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