Android, Best way to provide app specific constants in a library project?

后端 未结 3 1769
走了就别回头了
走了就别回头了 2021-02-13 12:26

I am creating a library project for a number of android apps. The apps all have some common functionality that I wish to include in the library project but the library project f

相关标签:
3条回答
  • 2021-02-13 12:48

    define them as enum's in your library project, like

    public enum Planet { MERCURY, VENUS, MARS }
    

    android proper takes another approach, the dreaded constant interface, like,

    interface Planets {
      static final int MERCURY = 1;
      static final int VENUS = 2;
      ...
    }
    

    however, this is a well-known java anti-pattern (constant interface, and is covered in detail in Effective Java, i quote,

    The constant interface pattern is a poor use of interfaces. That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail to leak into the class’s exported API. It is of no consequence to the users of a class that the class implements a constant interface. In fact, it may even confuse them. Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the constants, it still must implement the interface to ensure binary compatibility. If a nonfinal class implements a constant interface, all of its subclasses will have their namespaces polluted by the constants in the interface.

    if you need the constants to have int values for some reason, and calling toString() on the enum isn't sufficient, you can give the enum's a extra information like,

    public enum ZipCode {
      LYNNWOOD(98036), SAN_JOSE(95112), ...;
    
      private int zipCode;
    
      private ZipCode(int zipCode) { this.zipCode = zipCode; }
    
      public int getZipCode() { return zipCode; }
    }
    

    Note that enum's are slightly less performing than integer constants, but from a code organization and clarity perspective they are far superior.

    0 讨论(0)
  • 2021-02-13 12:50

    I don't know of a great schema to do that but it would certainly work this way:

    define some base class in your library

    // class, enum or whatever you want it to be. 
    class BaseConstants {
        // use some real singleton instead
        public static final BaseConstants instance = new BaseConstants();
    
        // define those values - sadly static inheritance does not work
        private static final int APP_ID = 0;
        private static final int CURRENT_APP_ID_KEY = 24;
    
        // so we have to do that via methods
        protected int getAppId() {
            return APP_ID;
        }
        protected int getAppIdKey() {
            return CURRENT_APP_ID_KEY;
        }
    }
    

    let each Activity that wants something custom implement that

    class App1Constants extends BaseConstants {
        public static final App1Constants instance = new App1Constants();
    
        private final static int APP_ID = 1;
    
        // want a different APP_ID here.
        protected int getAppId() {
            return APP_ID;
        }
    
        // getAppIdKey not implemented here, uses default
    }
    

    Use that class as context to the constants for your library

    class Library {
        public static long getCurrentAppId(Context context, BaseConstants settings) {
            return getLongPreference(context, settings.getAppIdKey(), settings.getAppId());
        }
    }
    

    Activities would be like so

    class myActivity extends Activity {
        // each Activity can implement it's own constants class and overwrite only some values
        private static final BaseConstants CONSTANTS = App1Constants.instance;
    
        private void whatever() {
            long appId = Library.getCurrentAppId(this, CONSTANTS);
        }
    }
    
    class myActivity2 extends Activity {
        // or could just use the default ones
        private static final BaseConstants CONSTANTS = BaseConstants.instance;
    
        private void whatever() {
            long appId = Library.getCurrentAppId(this, CONSTANTS);
        }
    }
    

    That schema is kind of ugly but it would work at least

    0 讨论(0)
  • 2021-02-13 12:58

    Option #1 Extend your AppConstants class in each project

    Better Option#2 Use XML resources to define the constants

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    <item type="integer" name="app_id" format="integer">6</item>
    </resources>
    

    then you can retrieve them by

    Context.getResources().getInteger(R.integer.app_id);
    

    add the xml file to your resources in each project with only the values you need different

    0 讨论(0)
提交回复
热议问题