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.

@OnResult to handle activity results #28

Description

@pyricau

Idea from @matboniface:

Instead of having to implement this :

protected  void onActivityResult(int requestCode, int resultCode, Intent data) {
 // Switch based on request code here
}

We could have an @OnResult(REQUEST_CODE) annotation, and the switch would be done by AndroidAnnotations

@OnResult(FOO_REQUEST_CODE)
void myFooResult(int resultCode, Intent data) {

}

@OnResult(BAR_REQUEST_CODE)
void myBarResult(int resultCode, Intent data) {

}

Activity

  1. naixx commented on Jul 9, 2012

    @naixx
    Contributor

    We can add additional parameter for annotation:

    @OnResult(request=BAR_REQUEST_CODE, resultCode=Activity.RESULT_OK)
    void myBarResult(int resultCode, Intent data) {
    
    }
    

    It would be useful to have some kind of builder (or rather, a getter) for intent data:

    @OnResult(request=BAR_REQUEST_CODE, resultCode=Activity.RESULT_OK)
    void myBarResult(int resultCode, Intent data) {
        int i = MyBuilder(data).field1();
    }
    

    Or even, specify such a builder as a param:

    @OnResult(request=BAR_REQUEST_CODE, resultCode=Activity.RESULT_OK)
    void myBarResult(int resultCode, MyBuilder data) {
        int i = data.field1();
    }
    
  2. pyricau commented on Jul 9, 2012

    @pyricau
    ContributorAuthor

    I like the idea of filtering using the result code, quite nice. Regarding the builder, I wouldn't want to go too far from the Android API... but that's an interesting idea. We already provide IntentBuilders for activities, maybe we should think about more general intent builders.

  3. naixx commented on Sep 4, 2012

    @naixx
    Contributor

    Ok, new idea:

    @OnResult(request=BAR_REQUEST_CODE, resultCode=Activity.RESULT_OK)
    void myBarResult(String fromExtraArg1, Boolean fromExtraArg2) {
        ...
    }
    

    We can have default resultCode as 'Activity.RESULT_OK' to reduce number of params in the annotation. And we can somehow combine request param and method name.

  4. pyricau commented on Sep 5, 2012

    @pyricau
    ContributorAuthor

    And we can somehow combine request param and method name.

    Sorry, I do not understand. How would you combine them exactly ?

  5. mathieuboniface commented on Oct 14, 2012

    @mathieuboniface
    Contributor

    I started to work around that issue.

    You can take a look at the 28_OnResultHandleActivityResults branch to see changes (https://github.com/excilys/androidannotations/tree/28_OnResultHandleActivityResults).

    I have not finished to work on it, I will come back later to explain changes.

  6. naixx commented on Oct 14, 2012

    @naixx
    Contributor

    @matboniface , great to hear!

    It could be an issue, if someone defines request codes as ids in resource xml in a library project. So, it could be useful to have resName and use if instead of switch in the generated code.

  7. mathieuboniface commented on Oct 15, 2012

    @mathieuboniface
    Contributor

    Oh damn it ! The commit diff is really weird, I will fix this dirty Windows based dev environnement bullshit !

  8. mathieuboniface commented on Oct 15, 2012

    @mathieuboniface
    Contributor

    Fixed weird commit.

    Ok @naixx, I see but what value should we consider ?

    • The generated int by aapt ?
    • The declared value into xml ?

    Is it a really good practice to declare those values as resources ?

    Actually this code :

        private static final int REQUEST_CODE = 2;
    
        private static final int ANOTHER_REQUEST_CODE = 3;
    
        @OnResult(REQUEST_CODE)
        void onResult() {
        }
    
        @OnResult(ANOTHER_REQUEST_CODE)
        void onResultWithData(Intent intent) {
        }
    
        @OnResult(REQUEST_CODE)
        void onResultWithIntResultCode(int resultCode) {
        }
    
        @OnResult(REQUEST_CODE)
        void onResultWithIntegerResultCode(Integer resultCode) {
        }
    
        @OnResult(ANOTHER_REQUEST_CODE)
        void onResultWithResultCodeAndData(int result, Intent intent) {
        }

    Generate the following code :

        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            AwaitingResultActivity_.super.onActivityResult(requestCode, resultCode, data);
            switch (requestCode) {
                case  2 :
                    AwaitingResultActivity_.this.onResult();
                    AwaitingResultActivity_.this.onResultWithIntResultCode(resultCode);
                    AwaitingResultActivity_.this.onResultWithIntegerResultCode(resultCode);
                case  3 :
                    AwaitingResultActivity_.this.onResultWithResultCodeAndData(resultCode, data);
                    AwaitingResultActivity_.this.onResultWithData(data);
            }
        }
  9. naixx commented on Oct 15, 2012

    @naixx
    Contributor

    @matboniface, actually I don't know whether it is good practice or not :) but it can be an issue. Sometimes it is useful to declare request ids in xml.

    If I understood you correctly, we should refer the generated R.id.my_request if the appropriate resName provided. if it is not, we will get compiler error in library projects. Non constant values can not be used in annotations, or smth like this.

    If we have a constant value, probably we can use it directly. Seems there would be no problem in non library projects, what do you think?

  10. pyricau commented on Oct 16, 2012

    @pyricau
    ContributorAuthor

    I just talked with @matboniface, and here is my opinion : I think using constants is bad. There's a habit of doing that in Android, but we're not here to promote bad habits. Using Android ids works, generates less noise, and avoids the risks of forgetting to update the constant values etc.

    So I would think of turning @OnResult into an annotation that only accepts "R.id" constants. And add a few lines to the docs to teach users how to add ids in their xml, since that's what they should do anyway. And we should of course also allow the "method name" convention, ie you could do :

    @OnResult
    void showSomeActivityResult() {}

    Would be equivalent to :

    @OnResult(R.id.showSomeActivity)
    void showSomeActivityResult() {}

    Thoughts ?

  11. mathieuboniface commented on Oct 16, 2012

    @mathieuboniface
    Contributor

    Ok, seems good to me.

    We should also explain in the documentation how to create an id into xml resources (http://developer.android.com/guide/topics/resources/more-resources.html#Id)

  12. naixx commented on Oct 16, 2012

    @naixx
    Contributor

    That's a good decision. The only problem I see - android docs teach users to use constants.

  13. mathieuboniface commented on Oct 17, 2012

    @mathieuboniface
    Contributor

    Hi folks !

    I updated the code following your suggestions.
    I also renamed @OnResult to @OnActivityResult I think it's more understandable and Android-API-compliant.

    Now, the following code (extracted from tests) :

        @OnActivityResult(R.id.first_request)
        void onResult() {
        }
    
        @OnActivityResult(R.id.second_request)
        void onResultWithData(Intent intentData) {
        }
    
        @OnActivityResult
        void secondRequestResult(int result, Intent intentData) {
        }
    
        @OnActivityResult(R.id.third_request)
        void onResultWithIntResultCode(int resultCode) {
        }
    
        @OnActivityResult(R.id.third_request)
        void onResultWithIntegerResultCode(Integer resultCodeInteger) {
        }
    
        @OnActivityResult({ R.id.first_request, R.id.second_request })
        void firstAndSecondRequestResult(Integer resultCodeInteger) {
        }
    
        @OnActivityResult(resName = { "third_request", "second_request" })
        void secondAndThirdRequestResult(Integer resultCodeInteger) {
        }

    Generates the following code :

        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            AwaitingResultActivity_.super.onActivityResult(requestCode, resultCode, data);
            if (requestCode == id.first_request) {
                AwaitingResultActivity_.this.onResult();
                AwaitingResultActivity_.this.firstAndSecondRequestResult(resultCode);
            } else {
                if (requestCode == id.third_request) {
                    AwaitingResultActivity_.this.onResultWithIntResultCode(resultCode);
                    AwaitingResultActivity_.this.secondAndThirdRequestResult(resultCode);
                    AwaitingResultActivity_.this.onResultWithIntegerResultCode(resultCode);
                } else {
                    if (requestCode == id.second_request) {
                        AwaitingResultActivity_.this.secondAndThirdRequestResult(resultCode);
                        AwaitingResultActivity_.this.secondRequestResult(resultCode, data);
                        AwaitingResultActivity_.this.onResultWithData(data);
                        AwaitingResultActivity_.this.firstAndSecondRequestResult(resultCode);
                    }
                }
            }
        }
  14. pyricau commented on Oct 18, 2012

    @pyricau
    ContributorAuthor

    Great !! I'll have a look. Does inverting the parameter order also work ? Such as :

        @OnActivityResult
        void secondRequestResult(Intent intentData, int result) {
        }

    Another detail : AwaitingResultActivity_.this shouldn't be needed in the generated code, this should be enough.

  15. mathieuboniface commented on Oct 18, 2012

    @mathieuboniface
    Contributor

    I have removed the useless references to activity into the last commit.

    Of course, you can invert parameters order. I have added the following test method :

        @OnActivityResult
        void secondRequestResult(Intent intentData, int result) {
        }

    Now, the generated code look like this (see the two secondRequestResult(...) calls) :

        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            AwaitingResultActivity_.super.onActivityResult(requestCode, resultCode, data);
            if (requestCode == id.first_request) {
                onResult();
                firstAndSecondRequestResult(resultCode);
            } else {
                if (requestCode == id.third_request) {
                    onResultWithIntResultCode(resultCode);
                    onResultWithIntegerResultCode(resultCode);
                    secondAndThirdRequestResult(resultCode);
                } else {
                    if (requestCode == id.second_request) {
                        secondRequestResult(data, resultCode);
                        onResultWithData(data);
                        secondAndThirdRequestResult(resultCode);
                        secondRequestResult(resultCode, data);
                        firstAndSecondRequestResult(resultCode);
                    }
                }
            }
        }
  16. added a commit that references this issue on Apr 13, 2013
    3b4b3a0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions