草庐IT

android - Gradle for Android、AAR 和条件依赖

coder 2023-11-18 原文

简表 :有哪些组织 AAR 的代码/POM 的方法,这样使用该 AAR 的应用程序只有它们实际需要的依赖项?

长表 :

假设我们有一个依赖于打包为 AAR (L) 的 Android 库项目的应用程序。

L 包含多个类,任何给定的应用程序(如 A)只会使用这些类的子集。例如:

  • L 可能包含 Fragment native API 级别 11 fragment 、反向移植 fragment 和 ActionBarSherlock 风格 fragment 的实现
  • L 可能包含 Activity常规 Activity 的实现,FragmentActivity , ActionBarActivity , 和 ActionBarSherlock 风格的 Activity
  • L 可以通过 LocalBroadcastManager 引发事件、Square 的 Otto 和 greenrobot 的 EventBus
  • 等等

  • 在我看来,这些案例有两个主要的共同点:
  • 应用程序通常只关心某些类。例如,使用 Otto 的应用程序不会关心引用 greenrobot 的 EventBus 的代码,或者使用 ActionBarActivity 的应用程序。不会关心 ActionBarSherlock。
  • 如果 AAR 是存储库中的 Artifact ,则应用程序将不会关心构建 AAR 所需的所有可能的上游依赖项。例如,使用 native API 级别 11 fragment 的应用将不需要 support-v4actionbarsherlock ,即使 AAR 本身需要它们来构建 AAR

  • 如果我们使用 JAR 而不是 AAR 并转储依赖管理,这相当简单。构建 JAR 将具有编译时依赖项(例如,support-v4)。但是,使用该 JAR 的应用程序可以跳过这些依赖项,只要这些应用程序不使用真正需要这些依赖项的类,生活就很好。

    但是,我很难看到如何使用 build.gradle 中指定的 AAR 和 Maven Artifact 来完成相同的事情。文件。如果 L 有 dependencies阻止引用上游依赖项,当应用程序依赖 L 时,应用程序将依次下载这些依赖项。

    我相当确定可行的一种解决方案是将 L 拆分为多个库。例如,使用 fragment 场景,我们可以:
  • L1,包含原生 API Level 11 版本 fragment 的实现,以及其他场景所需的任何通用代码。该库将没有上游依赖项。
  • L2,其中包含使用 Android 支持包的 fragment 反向移植的实现。 L2 将依赖于 L1 和 support-v4 .
  • L3,其中包含使用 Sherlock 风格 fragment 的实现。 L3 将依赖于 L1 和 actionbarsherlock .

  • 然后,应用程序将选择是否依赖 L1、L2 或 L3,因此只会获得必要的上游依赖项(如果有)。

    我的问题是:这是最好的解决方案吗?或者在 Gradle for Android、AAR 和 Maven 风格的 Artifact 的世界中是否有其他东西可以让应用程序依赖于单个 L?我担心库可能会组合爆炸以处理上游依赖项的各种组合。我还担心实际上确实需要多个实现的古怪应用程序以及我们是否可以可靠地指定这些依赖项(例如,一个依赖于 L1 和 L2 的应用程序,因为这是该应用程序的作者认为该应用程序需要的)。

    我知道应用程序可以通过多种方式阻止 排除 依赖项(请参阅 Joseph Earl 的语法答案),因此应用程序可以依赖 L 但随后会阻止 actionbarsherlock如果不需要,则上游依赖。虽然这可行,但对于我是 L 的作者的情况,我宁愿采用 L1/L2/L3 方法,因为这看起来更简洁。

    还有其他建议吗?

    最佳答案

    我不知道任何可以帮助解决此问题的依赖项管理功能。

    拥有一个具有许多依赖项的库以及删除不需要的依赖项的能力可能会起作用,但是会带来一些问题:

  • 您必须依靠 L 的用户来删除正确的依赖关系。
  • 您将在库中拥有不容易用 Proguard 删除的类。 Proguard 不会删除扩展 Fragment/Activity/etc 的任何内容,并且 L 应该提供一个 proguard 规则文件以不删除扩展支持 Fragment/Activity/etc 的类...这将使删除不需要的类变得困难。
  • 一些实现可能有额外的资源,现在我们不能去掉不需要的资源。

  • 我认为拆分库是正确的做法,但是在我们对库项目有所了解之前,这样做会很复杂。一旦我们有了这个,我认为它会更容易处理。你不会有一个基本的 L1 和 L2/L3 扩展它。相反,您将拥有一个生成不同变体的库,每个变体都有自己的依赖项。

    使用 flavor 维度,您可以处理支持库与事件库组合,但如果添加更多维度,您肯定会得到一些爆炸。

    多变体库的优点是更容易在变体子集之间共享代码,而无需引入更多的子库。您还可以在主代码和风格之间进行双向引用,这在 L2/L3 中无法实现,具体取决于 L1。

    至于支持 Ant/Eclipse,这肯定会很复杂。我会明确地忽略 Ant。如果有人只关心命令行构建,他们应该已经转移到 Gradle。
    至于 Eclipse,我们将在某个时候获得 Gradle 支持,但我理解您是否迫不及待。

    关于android - Gradle for Android、AAR 和条件依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20938158/

    有关android - Gradle for Android、AAR 和条件依赖的更多相关文章

    1. ruby-on-rails - 在 ruby​​ .gemspec 文件中,如何指定依赖项的多个版本? - 2

      我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这

    2. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

      我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

    3. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

      我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

    4. ruby - 在 Ruby 中有条件地定义函数 - 2

      我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

    5. ruby - 定义方法参数的条件 - 2

      我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

    6. 安卓apk修改(Android反编译apk) - 2

      最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

    7. ruby-on-rails - 使用包含多个关联和单独的条件 - 2

      我的Gallery模型中有以下查询:media_items.includes(:photo,:video).rank(:position_in_gallery)我的图库模型有_许多媒体项,每个都有一个照片或视频关联。到目前为止,一切正常。它返回所有media_items包括它们的photo或video关联,由media_item的position_in_gallery属性排序。但是我现在需要将此查询返回的照片限制为仅具有is_processing属性的照片,即nil。是否可以进行相同的查询,但条件是返回的照片等同于:.where(photo:'photo.is_processingIS

    8. ruby-on-rails - 在 haml View 中重构条件 - 2

      除了可访问性标准不鼓励使用这一事实指向当前页面的链接,我应该怎么做重构以下View代码?#navigation%ul.tabbed-ifcurrent_page?(new_profile_path)%li{:class=>"current_page_item"}=link_tot("new_profile"),new_profile_path-else%li=link_tot("new_profile"),new_profile_path-ifcurrent_page?(profiles_path)%li{:class=>"current_page_item"}=link_tot("p

    9. ruby-on-rails - 在具有 ActiveRecord 条件的相关模型中按字段排序 - 2

      我正在尝试按Rails相关模型中的字段进行排序。我研究的所有解决方案都没有解决如果相关模型被另一个参数过滤?元素模型classItem相关模型:classPriority我正在使用where子句检索项目:@items=Item.where('company_id=?andapproved=?',@company.id,true).all我需要按相关表格中的“位置”列进行排序。问题在于,在优先级模型中,一个项目可能会被多家公司列出。因此,这些职位取决于他们拥有的company_id。当我显示项目时,它是针对一个公司的,按公司内的职位排序。完成此任务的正确方法是什么?感谢您的帮助。PS-我

    10. ruby - 有什么方法可以告诉 sidekiq 一项工作依赖于另一项工作 - 2

      有什么方法可以告诉sidekiq一项工作依赖于另一项工作,并且在后者完成之前无法开始? 最佳答案 仅使用Sidekiq;答案是否定的。正如DickieBoy所建议的那样,您应该能够在依赖作业完成时将其启动。像这样。#app/workers/hard_worker.rbclassHardWorkerincludeSidekiq::Workerdefperform()puts'Doinghardwork'LazyWorker.perform_async()endend#app/workers/lazy_worker.rbclassLaz

    随机推荐