Невозможно разрешить метод getAllUserGroupByName() из другой студии android android

Считаю, что у меня есть два продукта в моем проекте Android с именем "local" и "international". Я просто даю скелет моей ситуации, поэтому любезно игнорирую другие ошибки. Рассмотрим, что у меня уже есть другой источник Set для разных вкусов.

Теперь в моем "местном" вкусе мне нужен только один метод, как указано ниже.

// local flavor file
interface UserDao {
    List<User> getAllUser();
}

В моем международном вкусе мне также нужна дополнительная функция, чтобы получить пользователя в группе по имени. Итак, имея два метода.

// international flavor file
interface UserDao {
    List<User> getAllUser();
    List<User> getAllUserGroupByName();
}

Но проблема в том, У меня есть одно действие, из которого я вызываю этот метод. Когда я вызываю метод getAllUserGroupByName() из активности, он компилируется, если текущий вкус " международный", но он не будет компилироваться на " локальном", так как он не содержит этого метода.

Я пробовал называть этот метод, обертывая, если условие, как показано ниже,

// BuildUtils is my helper class to get current flavor check easily.
if (BuildUtils.isInternational()) {
      getAppDatabase().UserDao().getAllUserGroupByName();
}

Но он тоже не работает.

Мне не нужно следующее решение.

  • Два действия для каждого вкуса.
  • Я уже решил это, объединив оба интерфейса в одном интерфейсе. (который также действителен, так как он не содержит никакой реализации).

Обновление

После некоторых исследований и ответов, предоставленных @manouti

Проблема в том, что Java является статически типизированным языком, поэтому размещение если условие не означает, что компилятор избегает проверки код с вызовом getAllUserGroupByName.

Итак, есть ли способ, с помощью которого система сборки может игнорировать конкретный код в соответствии с вкусом для компиляции кода?

ИЛИ

любой инструмент или функция IDE для студии Android, которая отбросит конкретный код в соответствии с вкусом для компиляции.

Ответ 1

Есть несколько способов сделать это. Конечно, вы можете написать два разных класса активности, как упомянутый другой ответ, и поместить их в каждый набор источников вкусов, и это будет отлично работать. Но я предполагаю, что вы действительно не хотите этого делать, потому что это было бы излишним дублированием кода, возможно, с очень небольшим изменением между двумя версиями.

Вот два способа, о которых я могу думать, которые позволяют сохранить только один класс Activity (т.е. в основном исходном наборе):

  • Используйте отражение, чтобы вызвать метод getAllUserGroupByName, если он определен. Детали этого подхода очень хорошо проиллюстрированы в этом сообщении. Проблема в том, что Java является статически типизированным языком, поэтому размещение условия if не означает, что компилятор избегает проверки кода с помощью вызова getAllUserGroupByName. С помощью этого решения вы можете использовать рефлексию, чтобы проверить, определен ли метод, и если это так, вы можете называть его рефлексивно.

  • Другое решение, которое IMO чище, чем использование кода отражения, заключается в инкапсуляции логики получения информации о группе пользователей в своем классе и в том же пакете, скажем UserGroupLoader, и определении двух версий этого класса, одного для каждого аромата. В локальном вкусе реализация вернет фиктивный результат (например, пустой список пользователей) и в международном вкусе он будет использовать фактический код загрузки пользователей:

    public class UserGroupInfoLoader {
        public List<User> getAllUserGroupByName() {
            // for international flavor, call UserDao.getAllUserGroupByName
            // for local flavor, return empty list (you may even use the Optional class as a return type instead of List<User>)
        }
    }
    

Вы также можете управлять областью логики для инкапсуляции в этом классе. Например, вместо того, чтобы просто возвращать список групп пользователей, вы можете вернуть ему объединенный результат как всех пользователей (первый метод в UserDao), так и всех пользователей по имени группы (применяется только к реализации для международного вкуса). Это делает код более читаемым, потому что просто наличие метода, который возвращает фиктивные данные для одного аромата, может показаться противоречивым для читателей.

Ответ 2

Вы можете создать интерфейс, содержащий только метод getAllUserGroupByName() и сделать его доступным для международной версии.

С помощью этого вы можете выполнить проверку экземпляра userDao.

Интерфейс с методом getAllUserGroupByName() (он должен быть помещен в общий набор источников):

interface InternationalInterface {
    List<User> getAllUserGroupByName();
}

Сделайте UserDao в международной версии, расширьте его:

// international flavor file
interface UserDao extends InternationalInterface {
    List<User> getAllUser();
}

И в вашей деятельности проверьте, является ли UserDao экземпляром InternationalInterface. Если утверждение будет верно только для приложения, созданного с использованием международного вкуса. Теперь вам больше не нужно использовать BuildUtils.

UserDao userDao = getAppDatabase().UserDao();
if (userDao instanceof InternationalInterface) {
    ((InternationalInterface)userDao).getAllUserGroupByName();
}

Ответ 3

Как сделать ваш текущий вид деятельности абстрактным с помощью метода типа:

protected abstract void onGetAllUserGroupByName();

а затем продолжите его с двумя версиями того же действия, что и

public class MyActivityImpl extends MyActivity {

     @Override
     protected void onGetAllUserGroupByName() {
         ...
     } 
}

Когда аромат локальный, то переопределенный метод пуст, а когда он международный, он будет:

@Override
protected void onGetAllUserGroupByName() {           
    getAppDatabase().UserDao().getAllUserGroupByName();
} 

Вам не нужно будет копировать любые ваши функции, уже присутствующие в родительской активности.