Command pattern to pass application's activity methods?
Asked Answered
M

1

7

After reading the the Avoiding memory leaks article by @RomainGuy I realized that my current Android application is plagued with the mistake of passing the application's main activity around. So whenever I, can I simply replace that activity parameter with Activity.getApplicationContext().

But there are certain classes in my application that still need to run methods that can only be members of the applications main activity.

Thus I was thinking of possibly using the Command Pattern to workaround this limitation.

The problem is that, if we look at that example:

public class SomeCommandExecuableOnlyByActivity implements Command 
{
    public void execute(Object data) 
    {
        doIt( ((MyActivity)data).getWindow() );
    }    
}

I am running again into the dead end of needing the pass around the activity (this time disguised as Object data).

How do I get out of this "chicken & the egg" situation?

Is there a better way to approach this problem?

Mather answered 2/7, 2012 at 13:5 Comment(6)
There is nothing in that article that claims that "passing the application's main activity around" is a mistake. Putting it in static data members is a mistake, and that's the core issue behind his first and third bullets at the bottom of the article. IMHO, only use Application when you specifically and precisely know why you are using it. It is not a blanket replacement for Activity, particularly for UI work.Argillaceous
@Argillaceous Thanks for pointing this significant difference out. In my case I keep a static SharedPreferences data member in my main Activity for easy access by the various modules in the application. So I can access the shared preferences by avoiding passing the main Activity as a parameter: MainActivity.staticPrefs. Is this considered "Putting it in static data members"?Mather
That's a good question. Since SharedPreferences is an interface, and I do not readily see where the concrete implementation is, I don't know. If the SharedPreferences does hold onto a Context -- and it might -- then you would either need to use Application or avoid the static data member. I would expect Application to work fine with a SharedPreferences.Argillaceous
SharedPreferences doesn't hold on to any Context. In fact, there is only one instance of SharedPreferences for each preferences-file within a given process. So there's no problem putting this in a static variable.Continuator
Generally, holding static references to framework objects sounds like a terrible idea to me. Almost everything in Android may hold a reference to Context, which would immediately leak if it's strongly reachable, in this case until the class is removed from memory. I have never, ever, heard a good reason why an object would have to be kept in a static reference. If your code requires you to do that, I would question the overall design of your code. (...)Essayistic
(...) What we do in our app is identify objects implementing cross-cutting concerns (like networking, i18n, databases, etc), and grant access to them from all components via a factory which itself is managed in the application context, i.e. it is guaranteed to live as long as the app does, and will never reference anything that's an activity or service. This factory can be implemented as a singleton class (it's the only singleton class we still use in our code.) Alternatively, frameworks like (Robo)Guice helps a lot taking these decisions of where to keep objects off your back.Essayistic
E
4

I think what you may be missing here is a proper separation of concerns. If you say you have to pass your main activity around to other activities in order to invoke some functionality on it, then it seems to me your app's architecture has some fundamental design flaws.

Whether or not to use the command pattern here I cannot tell, but what I'd generally do is identify those methods that require shared access, move them to a separate class and then either keep a separate instance of that class in all activities requiring this functionality, or if you need to share instance state, create it in the global application context and provide a global access path to it (not desirable, but without a DI framework like RoboGuice it's very difficult to implement DI on Android, since constructors are rendered void.)

In my opinion, in a well designed Android application, an Activity is free of business logic and only provides operations that change the state of the UI. The flow of the user interface or any other computations would be left to other classes. The Model-View-Presenter pattern helps tremendously here to keep your code structured by responsibility.

Without giving us more insight into what you're exactly trying to achieve, it's hard to give out specific advice though.

Essayistic answered 27/9, 2012 at 12:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.