Вот мой сценарий.Как абстрагироваться от зависимостей в коде библиотеки Android?
У меня есть андроид-активность, в которой я хочу абстрагироваться от зависимостей ввода-вывода. Зависимости представлены этим интерфейсом (под редакцией для краткости и простоты):
public interface ITimeDataServer {
TimeRecord[] get(int userID);
void save(TimeRecord record);
}
То, что я хочу, чтобы моя деятельность, чтобы иметь возможность вызывать эти методы интерфейса, а также оставить реализацию, подаваемую в коде вызова. (Довольно стандартный, я думаю).
ITimeDataServer myServer;
int myUserID;
void loadRecords() {
TimeRecord[] records = myServer.get(myUserID);
// etc...
}
Моя трудность в том, как я могу гарантировать, что myServer
получает набор?
Это кажется общей проблемой, но я не могу найти решение.
Моя первая мысль заключалась в том, что myServer
будет передан через конструктор, но действия Android на самом деле не создаются с помощью конструкторов.
Я придумал несколько решений, но они все неприглядные в некотором роде:
Icky Решение 1
Создать статический метод для запуска класса активности, который принимает параметр ITimeDataServer и сохраняет его в статической переменной, из которой активность может получить доступ к нему:
private static ITimeDataSource theDataSource;
public static void launch(Activity currentActivity, ITimeDataSource dataSource) {
theDataSource = dataSource;
Intent intent = new Intent(currentActivity, MainActivity.class);
currentActivity.startActivity(intent);
}
Это неприглядное, потому что (а) источник данных статичен и на самом деле не связан с экземпляром, и (б) потребитель может инициировать активность с помощью API стандартной активности, а не этот статический метод, который вызовет исключение NullPointerException.
Icky Решение 2
я могу создать класс поставщика, который обеспечивает одноэлементный экземпляр ITimeDataSource, который должен быть инициализирован вызывающей библиотеки перед использованием:
public class TimeDataSourceProvider {
private static ITimeDataSource myDataSource = null;
public void initialize(ITimeDataSource dataSource) {
myDataSource = dataSource;
}
public ITimeDataSource get() {
if (myDataSource == null)
throw new NullPointerException("TimeDataSourceProvider.initialize() must be called before .get() can be used.");
else
return myDataSource;
}
}
Это кажется немного менее icky, но это все еще немного неприятно, потому что зависимость активности не очевидна, и поскольку может быть много путей для ее запуска, очень возможно, что некоторые из них забудут позвонить TimeDataSourceProvider.initialize()
.
Icky раствор 3
Как вариант # 2, создать статический IODependencyProvider
класс, который должен быть инициализирован со всеми зависимостями при запуске приложения.
public class IODependencyProvider {
static ITimeDataSource myTimeData;
static IScheduleDataSource myScheduleData; // etc
public static void initialize(ITimeDataSource timeData, IScheduleDataSource scheduleData /* etc */) {
myTimeData = timeData;
myScheduleData = scheduleData;
//etc
}
public static ITimeDataSource getTimeData() {
if (myTimeData == null)
throw new NullPointerException("IODependencyProvider.initialize() must be called before the getX() methods can be used.");
else
return myTimeData;
}
// getScheduleData(), etc
}
Это, кажется, превосходит # 1 и # 2, так как неспособность инициализации будет гораздо труднее красться, но она также создает взаимозависимости между типами данных, которые в противном случае не должно существовать.
... и другие нехорошие вариации на эту тему.
общих темы, которые делают эти решения дерьмовым:
- необходимо использовать статические поля для передачи несериализуемой информации к деятельности
- отсутствия возможности принудительной инициализации этих статических полей (и последующее Стихия)
- неспособность четко идентифицировать зависимости какого-либо процесса (в связи с зависимостью от статики)
Что нужно сделать разработчику Android от nooby?
Если бы аннотацию для статической инициализации (), чтобы сказать: «Этот метод ДОЛЖЕН быть вызван во время запуска приложения», что облегчит, по крайней мере, вторую точку. –