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.

startActivityForResult in activity intent builder #270

Description

@naixx

It could be useful to have an overloaded method in intent builder

 public void start(int requestCode) {
     context_.startActivityForResult(intent_, requestCode);
 }

Activity

  1. pyricau commented on Jul 12, 2012

    @pyricau
    Contributor

    Yes, we thought about that, the only problem is that startActivityForResult is a method that only exists on the Activity class, not on the Context class. So this basically means we'd have to create two IntentBuilder class per Activity class.

  2. naixx commented on Jul 12, 2012

    @naixx
    ContributorAuthor

    Yep, missed that. Probably, it can be done smth like this, without generating fully same classes:

    public static class IntentBuilder2<T extends Context> {
        protected T context_;
        protected final Intent intent_;
    
        public IntentBuilder2(T context) {
            context_ = context;
            intent_ = new Intent(context, ValveData_.class);
        }
        ...
    }
    
    public static class ActivityIntentBuilder_ extends IntentBuilder2<Activity> {
        public ActivityIntentBuilder_(Activity context) {
        super(context);
    }
    
    public void start(int request) {
            ((Activity)context_).startActivityForResult(intent_, request);
        }
    
    }
    

    And additional static method in activity:

    public static<T extends Context> IntentBuilder2<T> intent(T context) {
        return new IntentBuilder2<T>(context);
    }
    
    public static ActivityIntentBuilder_ intent(Activity context) {
        return new ActivityIntentBuilder_(context);
    }
    
  3. pyricau commented on Jul 12, 2012

    @pyricau
    Contributor

    Yeah, that's an interesting solution. A few notes :

    • we don't need the cast in ((Activity)context_).startActivityForResult(intent_, request); , that's the whole point of using generics here :) .
    • The first method doesn't need to be parameterized, it will provide the same features this way :
    public static IntentBuilder2<Context> intent(Context context) {
        return new IntentBuilder2<Context>(context);
    }
    • I would name the start method startForResult()
  4. pyricau commented on Jul 12, 2012

    @pyricau
    Contributor

    Hum, giving it a few more thoughts, it can't work this way. The fluid API pattern requires using self bounded generics, to be able to do something such as : intent(activity).flags(0).startForResult(42) : flags() is defined in the supertype and returns this, but this is an instance of supertype, unless we have it return T, T being a self bounded generic.

    We could also go down the "unsafe but ok road", just add the following startForResult() method to the current implementation :

    public void starForResult(int requestCode) {
      if (context instanceof Activity) {
        ((Activity) context_).startActivityForResult(intent_, requestCode);
      } else {
        context_.startActivity(intent_);
      }
    }
  5. naixx commented on Jul 12, 2012

    @naixx
    ContributorAuthor

    Haven't tried yet, but what do you think?

    public static class IntentBuilder2<T extends Context, Super extends IntentBuilder2<?, ?>> {
        protected T context_;
        protected final Intent intent_;
    
        public IntentBuilder2(T context) {
            context_ = context;
            intent_ = new Intent(context, ValveData_.class);
        }
    
        Super data() {
            return (Super) this;
        }
    }
    
    public static class ACtivityIntentBuilder extends IntentBuilder2<Activity, ACtivityIntentBuilder> {
    
        public ACtivityIntentBuilder(Activity context) {
            super(context);
        }
    
    }
    
    public static<T extends Context> IntentBuilder2<T, IntentBuilder2<?,?>> intent(T context) {
        return new IntentBuilder2<T, IntentBuilder2<?,?>>(context);
    }
    
    public static ACtivityIntentBuilder intent(Activity context) {
        return new ACtivityIntentBuilder(context);
    }
    

    Probably, there is a solution for compile time checks.

  6. pyricau commented on Jul 13, 2012

    @pyricau
    Contributor

    Yeah, this is what I called "self bounded generics".

    As you probably noticed, I just implemented a "simpler" solution in #271.

  7. naixx commented on Jul 13, 2012

    @naixx
    ContributorAuthor

    Yep, saw that. I don't know, if it is possible to make a compile-time warning, when we call startForResult from non activity context. One of the main feature of AA is compile-time checks, and i like that :)

  8. pyricau commented on Aug 2, 2012

    @pyricau
    Contributor

    Agreed. However, for this specific case, I see no better solution.

  9. naixx commented on Aug 2, 2012

    @naixx
    ContributorAuthor

    @pyricau, why don't you want to use "self bounded generics"?

    The other issue, probably a warning should be, if we use startForResult with non activity code.

  10. pyricau commented on Aug 3, 2012

    @pyricau
    Contributor

    @naixx Because "self bounded generics" are a nice nerdy things that 99% of java developers know nothing about, and would be scared to hell when seeing what Eclipse tell them about the return type of the intent() method :) .

    We could have also created two IntentBuilder classes per activity, one that takes a context and one that takes an activity.

    We cannot put a compilation warning on method calls. Only on compilation elements (ie declarations). We could log a warning at runtime if the context isn't an activity, I guess.

  11. naixx commented on Aug 3, 2012

    @naixx
    ContributorAuthor

    @pyricau, But developers would see only clean interface, which will or not have startForResult, they don't even need to know about internal IntentBuilder classes. But it will provide them much more safety.

    I meant a runtime warning to the Log. In this case we need somehow to tell developer, that the program would not behave as expected(he will never receive a result). Probably even an exception could be thrown?

  12. pyricau commented on Aug 3, 2012

    @pyricau
    Contributor

    Although I like making my app crash in debug mode when something's unexpected, to force devs to fix it, I wouldn't enforce this in an open source framework :) . I think the runtime warning is a good enough solution.

    Regarding the self bounded generic, the developer will use the autocompletion and see in the autocompletion doc that "intent()" returns a weird type and get scared :) . At least that's my theory.

  13. reopened this on Aug 3, 2012
  14. naixx commented on Aug 3, 2012

    @naixx
    ContributorAuthor

    @pyricau Didn't check, but what if:

    public static class ContextIntentBuilder extends IntentBuilder2<Context, ContextIntentBuilder > {
    
        public ContextIntentBuilder(Context context) {
            super(context);
        }
    
    }
    

    So, we will have ContextIntentBuilder and ActivityIntentBuilder that will be returned from intent(). Is it possible in Java?

    Yep, warning would be good anyway.

  15. pyricau commented on Aug 3, 2012

    @pyricau
    Contributor

    Yes, it's possible but doesn't change a thing on the signature of methods implemented by IntentBuilder2 :) . The'll still return a IntentBuilder2<>, <>, with capture-of* adding a lot of noise :)

  16. naixx commented on Aug 3, 2012

    @naixx
    ContributorAuthor

    @pyricau Actually, i didn't clearly understand the problem. IntentBuilder2<>, <> is hidden, so whats the noise?

  17. pyricau commented on Aug 3, 2012

    @pyricau
    Contributor

    When you write MyActivity_.intent(context).flags(0) and let Eclipse show you the signature of the flags() method. This method belongs to IntentBuilder2<>, <>.

  18. naixx commented on Aug 3, 2012

    @naixx
    ContributorAuthor

    Ok, now i understand :) For me, its not so scary. Developer won't see this class in his own code, only auto-completion in IDE. There are a lot of generics in standard library and even android (e.g. Simple*Adapters), but people use them :).

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

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions