4

I am considering how I can add tasks to Android Activities in a flexible way. I can only use implementation inheritance for one thing in Java and I would like to use it, if I use it at all, for something else.

I think I need to draw the domain first a bit:

Activities are UI windows basically, with intrinsic lifecycle responsibilities enforced by the API. The tasks I speak of are UI-visible popovers that do some offline stuff and then disappear. They stem from AsyncTasks. The code of all of this is not a problem, I have this already, even pretty generalized with interfaces. I'm looking at further design improvements I can make.

There are many type of activities and they could all work with some types of tasks. For instance a search window would have a task that adds one of the search results, let's say it's a book, to the collection of books in the main application. It allows you to add multiple, hence the popover. A window that displays the collection has a task that lets you export a book to an external file format. It won't stop you from browsing through your collection, yet it needs to display a progress bar as it may take a while to export.

A specific Task exists as a nested class in a specific Activity. It needs to be saved away and restored along with lifecycle events: there's a onSaveInstanceState(Bundle) and onRestoreInstanceState(Bundle) for that, among others. The Activity has a list of active tasks (or just a member for one task). Some UI event will create a new task and add it to the list, a la onClick(): ATask task = new ATask(); task.execute(something);.

Here's what I have considered so far:

  • Implementation inheritance

    Just move this task business to an abstract super class of all specific activities.

  • Decorator pattern

    Create a TaskedActivityDecorator that would add this responsibility on any activity. The decorator would have to mimic the entire Activity interface as provided by the API, mostly passthroughs though. So this may already be a bit too heavyweight. It would also need to add the UI events/buttons that launch the task, which may not always be possible if the action is more consequential.

    But the biggest problem I could come up with here is that Android uses a manifest to loosely couple all activities together. Therein you need to declare every specific activity or it can not be used. This is a problem because the decorator would work at runtime, with composition. I can't declare the decorator and add in the information that it needs to wrap a specific activity.

    With Android I seem to end up with implementation inheritance a lot more than I'd like to. Hence I have too much coupling or code duplication. The activities always easily grow out to big fat classes. Am I correct to say that that is partly because of existing design choices in the Android framework, such as the manifest taking away composition solutions, or the Context object? Am I correct to say that from the get-go it cuts away a significant amount of established design patterns in key areas, including the MVC pattern.

  • Decorator with wrappers:

    That I can't specify the decorator and the specific activity it applies to together in the manifest, doesn't mean I can't create classes that represent and arrange this composition. I could of course create many SpecificDecoratorActivity classes, that also implement the Activity interface and act like the decorator, and then wrap in the real specific activity. I'm not sure if it solves my problem though. It seems like a lot of work, a lot of rubbish classes, and takes me far from my original goal.

  • Strategy pattern:

    If I can't skin the activity, then I'd better outsource part of its guts. This will give me yet more connections though as the activities will need to know about the Strategy. The Strategy itself however will be more lightweight as a Decorator. Yet it feels not so much like Strategy where there is a choice of which one, but rather just moving part of the class to another class. I would call it TaskManager. And would I still pull up the strategies knowledge into an activity super class?

  • Any other pattern?:

Which pattern is the best choice? Don't shun your opinion on the specific Android case. No need to talk about tasks specifically.

3
  • Hi! This is a bit long, I did some formatting-fu to make it a little bit more readable, if you don't like it feel free to rollback
    – yannis
    Dec 31, 2011 at 15:49
  • Thanks, I was going to after proof reading, but it's a lot better.
    – pjv
    Dec 31, 2011 at 16:02
  • Let me know if my answer makes sense - I may just not understand how your classes currently work. It's tough without at least a class diagram, and as I state, I have done no Android development.
    – psr
    Jan 23, 2012 at 19:28

2 Answers 2

0
+50

First, I don't know anything about Android development, so I was waiting for someone else to answer you, but since you haven't gotten a lot of responses:

What about the Bridge pattern? This isn't the canonical case described in Design Patterns, but it sounds like it might fit, since what you want is to have separate hierarchies with implementation inheritance (one for tasks and one for activities).

This is similar to what you discussed as a strategy pattern, and yes, it is moving part of the class to another class, but to a new class that doesn't have the limitations (i.e., the manifest) of the old. I'm not sure this gives you more connections - a reference seems a weaker connection than a nested class.

As far as putting the strategies knowledge into an activity super class, you could, but you did state that you would rather use implementation inheritance for something else. If so you could put into an interface instead.

8
  • The manifest in Android is one big xml file that lists the windows that can be shown (Activities) and which class needs to be instantiated for that.
    – pjv
    Jan 23, 2012 at 20:26
  • Yes, the Bridge pattern describes very well what I was trying to say in the 'Strategy' pattern as well. +1 for bringing up possibly the better terminology. Especially when I want to pull up the Strategies knowledge, it sounds a lot more like the Bridge pattern (Abstraction).
    – pjv
    Jan 23, 2012 at 20:39
  • Please clarify "If so you could put into an interface instead."? As I see it, this is just the Abstraction bit of the Bridge pattern, but more complicated. I can put it in or leave it. I say "more complicated" because Activities come with a lot of to-be-implemented template methods that tie into the behavior of the parts I'm now moving to the (Concrete)Implementor. Even though all these little methods will be link-throughs to the Implementor, they constitute boilerplate code, that I'd like to deduplicate. Worse, RefinedAbstraction code may need to be there as well, and in the right order.
    – pjv
    Jan 23, 2012 at 20:46
  • The "order" matters because a lifecycle template method in the RefinedAbstraction may need to do in sequence: "A - B - C". Where B is the Implementor's work. Another RefinedAbstraction may need to do in sequence: "E - F -B". 90% of the RefinedAbstractions have just "B". This makes it hard to pull up this code for sharing and to have the least amount of duplicate code or boilerplate code remaining in the long run. That's part of my dilemma. Thanks for your opinion.
    – pjv
    Jan 23, 2012 at 20:49
  • Since this isn't talking about a decorator pattern, when I say you could put the reference to the implementer in an interface I mean the ICanHazActions interface, not the whole Activity in an interface, and have your activities implement ICanHazActions.
    – psr
    Jan 23, 2012 at 21:11
0

I think I don't fully understand what you're trying to accomplish, it was a lot to read, but I think I can say a couple things. You mentioned that Android doesn't have design patterns like MVC, I can say that this isn't correct. Android native classes play pretty nicely with POJOs, I think you can structure a lot of things however it makes the most since to.

1
  • I guess my question is: Aren't Activities good candidates to use the decorator pattern on (in the case where you have many activities)? But the manifest interferes. How do you structure both visible (UI elements) and invisible (actions, techniques) app-level consistencies on the UI on top of these Activities?
    – pjv
    Jan 16, 2012 at 22:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.