Where should I put global methods and variables in

2020-07-18 20:22发布

When I'm writing a method or using a member variable, I often find I need to share them across an app. But where should they go?

I can subclass Activity, but that falls over as soon as I use a MapView and am forced to use MapActivity, so not all my activities inherit from my subclass. Is there I way around this?

Where inheritance isn't applicable, I am tending to put generic methods and member variables into a subclass of the Application object, but I'm finding it's creating a mess of code as every class needs to either grab access to the application object through via context, or I have to pass it down.

I suspect I would be better off creating MyApplication.getInstance() and keeping everything in a singleton, instead of passing the application object down through the app classes. but before I wanted to see what you guys had to say.

标签: android
3条回答
啃猪蹄的小仙女
2楼-- · 2020-07-18 20:49

For global methods, use a static Util class with static methods. If you can't use static methods, then the methods shouldn't be global in the first place, and put them in the class that makes sense.

查看更多
▲ chillily
3楼-- · 2020-07-18 20:51

First read this:

How to declare global variables in Android?

Now why you shouldn't use a static singleton. Using a singleton is a the same thing as a global variable. Global variables reduce your maintainability because everywhere you use the global variable you break modularity or introduce global details and assumptions about your overall design. Your program can't have two of these variables because it only looks in one place for it. This means your program can't adapt easily when you have two instances instead of one.

For example, say I have a method called playTurn() and I implement it like so:

public void playTurn() {
   globalPlayer.incrementClock();
   globalPlayer.doSomething();
   globalPlayer.doSomethingElse();
}

Now let's say I want to add a second player to the mix. Uh oh my playTurn() method assumes one player only when it used globalPlayer. If I want to add a second player to the program I have to change that method. Do this a lot and your program is very rigid and inflexible to change. Instead what if I did this:

public void playTurn(Player player) {
   player.incrementClock();
   player.doSomething();
   player.doSomethingElse();
}

Now can do this:

playTurn( player1 );
playTurn( player2 );

I can reuse playTurn() for both player1 and player2 and I didn't have to change it. I just had to change the client of that method.

Most of the time you're being lazy and you want to get a reference to some object, and global variables are fast ways to get references to well known objects. Instead it's better to have one class that resolves the dependencies across your application at start up or the time when it makes sense. Then only that one place understands how your code is put together. For example,

public class Game {
   Player player1;
   Player player2;
   Board board;

   public void startGame() {
      BlueTooth blueTooth = BlueTooth.getChannel();

      player1 = new LocalPlayer();
      player2 = new NetworkedPlayer( blueTooth );

      board = new Board();

      player1.setOpponent( player2 );
      player1.setBoard( board );
      player2.setOpponent( player1 );
      player2.setBoard( board );
  }
}

Now everyone has their dependencies, and they don't need to use static variables to find references to things. Also player1 doesn't have to know about details like that player2 is over the network, or that it's apart of a Game. What's important to note is that these objects we're connecting have a long life, possibly the entire program, but if they need to create other things at runtime that's ok for them to do.

Say for example, we need to create multiple players at runtime based on who joins the game. Well we might create a PlayerManager that we can instantiate at startup then create Player objects on the fly. PlayerManager is just a plain old object that we create in Game when we start a new game.

I hope you can start seeing this is a much better way to develop software. You might not understand it right off, but if you think about it will make more sense. It's very subtle change, but very powerful.

查看更多
冷血范
4楼-- · 2020-07-18 21:02

If you want to access the "Global Singleton" outside of an activity and you don't want to pass the Context through all the involved objects to obtain the singleton, you can just define, as you described, a static attribute in your application class, which holds the reference to itself. Just initialize the attribute in the onCreate() method.

For example:

public class ApplicationController extends Application {
    private static ApplicationController _appCtrl;

    public static ApplicationController getAppCtrl()
    {
         return _appCtrl;
    }
}

One example with resources: Because subclasses of Application also can obtain the Resources, you could access them simply when you define a static method, which returns them, like:

public static Resources getAppResources()
{
    return _appCtrl.getResources();
}
查看更多
登录 后发表回答