热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

彻底弄清support支持库,以及v4v7重复依赖问题深究

原文链接,感谢作者前言众所周知android提供了很多SupportLibrary作为api的补充,常见的有supprt-v4,v7等,但我发现这些支持库的版本众多,涉及的内容也比较庞

原文链接,感谢作者
前言
众所周知android提供了很多Support Library作为api的补充,常见的有supprt-v4,v7等,但我发现这些支持库的版本众多,涉及的内容也比较庞杂,本文带大家梳理一下常见的Support Library,然后文章后半部分对一个报错问题展开深究,那就是我们用开源库时经常碰到的v4重复依赖问题:DexException Multiple dex files define。

为何提供支持库
google为啥要弄这么多支持库,直接放到sdk里面不好么? 参阅官方文档有下面3个原因:

1.向后兼容
如,我们开的App需要支持的minSdkVersion=9,targetSdkVersion=11,在程序里使用了android 3.0 (API level 11)提供的ActionBar类,使用compileSdkVersion=11成功编译出apk。在android 3.0的设备上完美运行,但是app在android 2.3的设备就会crash,报找不到ActionBar的错误。这很好理解,因为旧版本上没有新版本里新增的类。为了避免使用了最新功能开发的app只能在最新系统的设备上运行的尴尬,官方把新版系统framework中新增加的接口提出来放到了Android Support Library(支持包)中,开发者在遇到上面的情况时,就可以使用支持包中具有同样功能的ActionBar类,这个支持包会打包进App里,这样使用了新版本系统上功能的App也可以向后兼容以前的老系统版本设备了。
使用支持包中的类除了让我们免于判断App运行的系统版本外,还可以使App在各个版本保持同样的用户体验。如在5.0以下系统使用material design。

2.提供不适合打包进framework的功能

Android官方对App开发提供了推荐设计,希望Android应用都有相对一致的交互设计来减少用户的使用成本,希望三方App类似系统应用从而完美融入到Android生态系统中。但是这都仅仅是推荐,不要求开发者一定要这样,如果有这种需求就可以使用官方支持包提供的这些功能,避免重复造轮子。如支持包中的DrawerLayout、Snackbar等类都是这种情况。

3.为了支持不同形态的设备

通过使用支持包来在不同形态设备上提供功能,如手机、电视、可穿戴设备等。

support-library支持库
Android 支持库提供了诸多未内置于框架的功能。这些库提供向后兼容版本的新功能、框架中未包含的实用 UI 元素,以及应用可以利用的一系列实用程序。比如

Material Design是Android 5.0加入的新功能,但是很多设备依然装的是Android4.0系统,如果为了Material Design将minSdkVersion设置为 api21显然不合理的,那为了Android5.0以下的设备可以使用Material Design的效果,就应该使用support-library,包括之前的Fragment和现在的权限检查,都是这个原理!

目前为止Android Support Library包含的依赖包有:比较常用的是1,2,3

这里写图片描述
support-v4
v4名称是最开始支持api level4的库,官方在Support Library 24.2.0版本的时候移除了对Android 2.2(API Level 8)及以下版本的支持,所以从Android Support Library 24.2.0开始,V4包支持的最低版本是Android 2.3即API Level 9),并且把v4库拆分成5个部分,可以在项目中按需要引用,但是必要性不是很大,一是因为这5个部分有依赖关系,二是compat库占了v4库的一半大小,v4库的依赖关系图:

这里写图片描述
比如下面这些都是v4包的内容:
Fragment:一个专为解决Android碎片化的类,通过它可以让同一个程序适配不同的屏幕。
NotificationCompat:支持更丰富的通知形式;
LocalBroadcastManager:适合于应用内的消息传递。
ViewPager:一个可以管理子view的viewgroup,用户可以在各个view之间自由切换,这个在很多应用中都有使用到;

上面说到v4是兼容level9之前的版本,那如果我们的compileSdkVersion>9是不是可以不用v4了? 这个不一定的,比如ViewPager这个类只在V4包中才有,在sdk中没有。

如何使用v4
compile ‘com.android.support:support-v4:21.0.3’
同步gradle之后,在ExternalLibrarys右键v4选择:library propertity查看依赖库的信息:

这里写图片描述

可以看到我们依赖的v4包就在sdk的extras目录:

这里写图片描述

这个是我们在androidStudio的SDK Manager中下载的,如果没有下载gradle同步后会让你去下载。
support-v7
V7和V4一样,同样包含多个依赖包,但和V4不同的是,V7下的多个子包并不是后面拆分开来的,而是最初发布时就以各个独立库的形式发布的。它是针对Android 2.3(API Level 9)及以上的版本谷歌提供了一系列的support包(和V4包的命名一样,V7最初支持的最低版本是Android 2.1即API Level 7,所以称其为V7,同样在Android Support Library 24.2.0将V7支持的最低版本改为Android 2.3即API Level 9了),这些support包各自对应着特定的功能,每一个都可以单独地被引用。

v7 app-compat这个包支持对Action Bar接口的设计模式、Material Design接口的实现等,核心类有ActionBar、AppCompatActivity、AppCompatDialog、ShareActionProvider等

如何使用v7
compile ‘com.android.support:appcompat-v7:24.2.1’
用这个maven方式配置v7会自动引入v4库,so不需要再额外引入v4库了。
gradle中jar依赖语句格式如 compile ‘jar文件组(group/命名空间):jar文件名(name):jar文件版本(version)’。所以上面的语句意思是依赖Android支持库中第24.2.1版的appcompat-v7库。

Multidex Support Library
当你的项目代码量越来越大的时候,会发现某一天运行在Android5.0以下的手机莫名崩溃。报错:某个类class not found,而这个类明明就有啊。。。其实这就是 著名的方法数超过 64K 的应用异常。解决办法就是这个支持库。

android {
defaultConfig {

minSdkVersion 15
targetSdkVersion 26
multiDexEnabled true
}

}

dependencies {
compile ‘com.android.support:multidex:1.0.1’
}
然后在自定义的Application的加入:

@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
v4 supportLibrary重复依赖深究
下面详细介绍 很常见的v4库的重复依赖问题,先抛出两个问题:

v7包含v4吗?
为啥问这个问题,源于我看网上很多文章,介绍v4的时候不假思索地下结论:v7包含v4!真的是这样吗???

我们打开v7的jar包看源码,其实appcompat-v7包本身是不包含v4的jar包的:

这里写图片描述
新建一个工程,加入v7的依赖包:

dependencies {
compile fileTree(dir: ‘libs’, include: [‘*.jar’])
compile ‘com.android.support:appcompat-v7:24.2.1’
}

看下项目目前的依赖包情况:

这里写图片描述
果然,项目自动引入了v4下面的所有包,v7包涵v4的意思是:

compile ‘com.android.support:appcompat-v7:24.2.1’, gradle会自动加入所有v4包的依赖,并且是和v7相同的版本

support库必须和compileVersion一致吗?
这里写图片描述
不是必须的。只是官方建议保持一致,如果版本不一致仍然可以编译运行。

v4包的重复依赖问题
上面已经证明依赖v7包会自动引入v4包,那么在项目中同时依赖v4和v7,会出现所谓的重复依赖编译报错吗?

这里写图片描述
可以成功编译运行安装,没有报错:

:mylibrary:preDebugUnitTestBuild UP-TO-DATE
:mylibrary:prepareDebugUnitTestDependencies
BUILD SUCCESSFUL
Total time: 7.005 secs

即使同时引入不同版本的v4包,也并没有出现包依赖重复的报错,可以正常编译运行:(注:红线是版本和compileSdkVersion不一致导致,此处忽略)

这里写图片描述
确实引入了不同版本的v4包:

这里写图片描述
结论: 如果都是maven的方式引入v4包,gradle会自动选择版本较高的,比如这里的21.0.3版本,不会导致冲突。
接下来,试试maven引入21.0.3的v4包,然后本地引入19.1.0的jar包:

这里写图片描述
运行时报错: dex文件冲突

这里写图片描述
当然,如果lib放入的和maven配置v4包版本21.0.3相同,是可以的。

(Android从support-20.0.0版本开始,v4的jar包全部升级为aar包),解压工具提取aar里面的classes.jar然后重命名为support-v4-21.0.3.jar放入lib文件夹

这里写图片描述
结论:v4的依赖冲突其实是不同版本v4的冲突,并且是本地lib和maven引入不同版本才会冲突
异常冲突解决办法
一个项目往往要引入很多开源库,试图统一所有moduler的v4版本是不现实的,只能通过exclude 方法过滤某些库的v4包,保证整个项目只引入一个版本。

  1. 首先查看当前项目各种库的依赖情况:

这里写图片描述
2. 找到里面版本冲突的依赖库,然后查找app项目,开源库的lib目录,删除对应的jar包改用maven形式引入。

  1. 如果你的app必须要使用本地lib引入v4库,那么就排除开源库的v4包:

compile(‘com.facebook.fresco:fresco:0.10.0’) {
exclude module: ‘support-v4’
}
如果是源码形式引入的开源库:

compile (project(‘:thirdpart:RecyclerViewAdapterLibrary’)){
exclude group: ‘com.android.support’
}


推荐阅读
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
author-avatar
张小白
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有