Android, лучший способ предоставить конкретные константы приложения в проекте библиотеки? - PullRequest
13 голосов
/ 18 марта 2012

Я создаю проект библиотеки для ряда приложений для Android.Все приложения имеют некоторые общие функции, которые я хотел бы включить в проект библиотеки, но функции проекта библиотеки требуют использования констант, специфичных для приложения

. Поэтому я ищу способ обеспечить функции библиотеки именамиконстанты и позволяют каждому приложению определять их

Пример конкретной константы приложения и способ ее использования в проекте библиотеки

public class AppConstants {
    public static final long APP_ID = 6;//Needs to be set for each app
}

public static long getCurrentAppId(Context context) {
    return getLongPreference(context, CURRENT_APP_ID_KEY, AppConstants.APP_ID);
}

Это всего лишь один пример примерно из 60 констант, которым требуетсябыть определенным для каждого приложения для большого количества библиотечных функций

Очевидно, что я обычно просто импортирую / включаю файл app_constants.java для конкретного проекта, но это невозможно в файлах проекта библиотеки, так как он не имеетподсказка о конкретных приложениях (правильно)

Так каков наилучший способ, чтобы каждое конкретное приложение переопределяло константы?

Обновление Я долго принимал решениена какой из превосходных ответов мне предоставили лучше всего подходит мойeds (спасибо всем) В конце концов я выбрал решение xml.Мне это не особо нравится, потому что оно загромождает ресурсы моих приложений, и я серьезно подумал об использовании интерфейсного решения, но решение xml работает хорошо

Ответы [ 3 ]

20 голосов
/ 18 марта 2012

Опция № 1 Расширьте свой класс AppConstants в каждом проекте*

добавьте файл xml к своим ресурсам в каждом проекте, используя только те значения, которые вам нужны

3 голосов
/ 18 марта 2012

Я не знаю хорошей схемы для этого, но она наверняка сработает так:

определите некоторый базовый класс в вашей библиотеке

// 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;
    }
}

пусть каждое действие, которое хочет что-то особенное, реализует это

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
}

Используйте этот класс в качестве контекста для констант для вашей библиотеки

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

Активность будет такой

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);
    }
}

Эта схема отчасти уродлива, но, по крайней мере, будет работать

1 голос
/ 18 марта 2012

определите их как enum в вашем библиотечном проекте, например

public enum Planet { MERCURY, VENUS, MARS }

Android действительно использует другой подход, страшный постоянный интерфейс , как,

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

однако, это хорошо известный Java-шаблон (постоянный интерфейс, подробно описанный в Effective Java, цитирую,

Постоянный шаблон интерфейса - плохое использование интерфейсов. Это класс использует некоторые константы внутри, это деталь реализации. Реализация постоянного интерфейса приводит к тому, что эта деталь реализации утечка в экспортированный API класса. Это не имеет никакого значения для пользователи класса, что класс реализует постоянный интерфейс. В На самом деле, это может даже сбить их с толку. Хуже того, это представляет собой обязательство: если в будущем выпуске класс будет изменен так, чтобы он больше не нуждался чтобы использовать константы, он все равно должен реализовать интерфейс для обеспечения двоичная совместимость Если нефинальный класс реализует константу интерфейс, все его подклассы будут загрязнены их пространства имен константами в интерфейсе.

если вам нужно, чтобы константы имели значения int по какой-то причине, и вызова toString () для перечисления недостаточно, вы можете предоставить перечислению дополнительную информацию, например,

public enum ZipCode {
  LYNNWOOD(98036), SAN_JOSE(95112), ...;

  private int zipCode;

  private ZipCode(int zipCode) { this.zipCode = zipCode; }

  public int getZipCode() { return zipCode; }
}

Обратите внимание, что перечисления немного менее эффективны, чем целочисленные константы, но с точки зрения организации кода и ясности они намного лучше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...