Repository navigation
@OnResult to handle activity results #28
Description
Activity
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(); }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.
Ok, new idea:
@OnResult(request=BAR_REQUEST_CODE, resultCode=Activity.RESULT_OK) void myBarResult(String fromExtraArg1, Boolean fromExtraArg2) { ... }We can have default
resultCodeas 'Activity.RESULT_OK' to reduce number of params in the annotation. And we can somehow combinerequestparam and method name.And we can somehow combine request param and method name.Sorry, I do not understand. How would you combine them exactly ?
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.
@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
resNameand useifinstead ofswitchin the generated code.Oh damn it ! The commit diff is really weird, I will fix this dirty Windows based dev environnement bullshit !
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); } }
@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?
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
@OnResultinto 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 ?
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)
That's a good decision. The only problem I see - android docs teach users to use constants.
Hi folks !
I updated the code following your suggestions.
I also renamed@OnResultto@OnActivityResultI 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); } } } }
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_.thisshouldn't be needed in the generated code,thisshould be enough.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); } } } }
- added a commit that references this issue
on Apr 13, 2013
Idea from @matboniface:
Instead of having to implement this :
We could have an @OnResult(REQUEST_CODE) annotation, and the switch would be done by AndroidAnnotations