繁体   English   中英

无法解析不同风味android studio的方法'getAllUserGroupByName()'

[英]Cannot resolve method 'getAllUserGroupByName()' of different flavor android studio

考虑我在我的android项目中有两个产品风味名为'local'和'international'。 我只是给出了我的情况的骨架,所以请不要理会其他错误。 考虑到我已经有不同的源Set为不同的味道。

现在我的'本地'味道我只需要下面提到的一种方法。

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

虽然在我的国际风格,我还需要其他功能,以使用户也可以通过其名称进入组。 所以有两种方法。

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

但问题是, 我正在调用该方法的单个活动。 当我从activity调用getAllUserGroupByName()方法时,如果当前flavor是' international ',它将编译,但它不会在' local '上编译,因为它不包含该方法。

我尝试通过如下条件包装来调用此方法,

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

但它也不起作用。

我不想要以下解决方案。

  • 每种口味的两种活动。
  • 我已经通过在单个界面中组合两个接口来解决它。 (这也是有效的,因为它不包含任何实现)。

更新

经过@manouti的一些研究和回答

问题是Java是一种静态类型语言,因此放置if条件并不意味着编译器将避免使用getAllUserGroupByName调用来检查代码。

那么构建系统是否可以根据代码编译的风格忽略特定代码?

要么

任何Android工作室IDE工具或功能,将根据编译风格丢弃特定代码。

有几种方法可以做到这一点。 当然,你可以像提到的另一个答案一样编写两个不同的Activity类,并将它们放在每个flavor的源集中,这样就可以了。 但我认为你并不是真的想要这样做,因为复制代码可能是一种过度杀伤,两个版本之间的变化可能很小。

以下是我能想到的两种方法,允许您只保留一个Activity类(即在主源集中):

  1. 如果已定义,则使用反射调用方法getAllUserGroupByName 这篇文章的细节在这篇文章中有很好的说明。 问题是Java是一种静态类型语言,因此放置if条件并不意味着编译器将避免使用getAllUserGroupByName调用来检查代码。 使用此解决方案,您可以使用反射来检查方法是否已定义,如果已定义,则可以反射性地调用它。

  2. 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第一个方法)和按组名称的所有用户(仅适用于国际风味的实现)的组合结果,而不仅仅返回用户组列表。 这使得代码更具可读性,因为只有一个返回一种风格的虚拟数据的方法对于读者来说似乎是违反直觉的。

您可以创建仅包含getAllUserGroupByName()方法的接口,并使国际版本扩展它。

有了这个,您可以对userDao进行instanceof检查。

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

如何通过以下方法使您的当前活动抽象:

protected abstract void onGetAllUserGroupByName();

然后用相同活动的两个版本扩展它

public class MyActivityImpl extends MyActivity {

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

当味道是本地的时候,被覆盖的方法是空的,当它是国际的时 ,它将是:

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

您无需复制父活动中已存在的任何功能。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM