Gradle基本知识点与常用配置

2023-11-11

http://blog.csdn.net/u010818425/article/details/52268126

查看原文:http://blog.csdn.net/u010818425/article/details/52268126

本文篇幅较长,文中系统地讲解了Gradle的基本知识点以及一些常用的命令和配置,适合于刚接触Gradle的同学;

在此基础上,可以阅读以下的实战经验文章: 
《Gradle实战:Android多渠道打包方案汇总》 
《Gradle实战:不同编译类型的包同设备共存》 
《Gradle实战:发布aar包到maven仓库》 
《Gradle实战:执行sql操作hive数据库》

(一)基本概念

1. Groovy

    Domain Specific Language,领域相关语言

2. Gradle

    Gradle是一个框架,它负责定义流程和规则;
    每一个待编译的工程都叫一个Project;
    每一个Project在构建的时候都包含一系列的Task。

3. Closure(闭包)

Closure是一段单独的代码块,它可以接收参数,返回值,也可以被赋值给变量:

    //无参数
    def Closure1 = { 
        println 'Hello world' 
    }
    Closure1() // 执行闭包,输出Hello world

    //接收一个参数
    def Closure2 = { 
        String str -> println str //箭头前面是参数定义,后面是执行代码,str为外部传入的参数
    } //如果只有一个参数可以用it代替,也可写作:
    def Closure2 = {
        println it
    }
    Closure2('Hello world')// 执行闭包,输出Hello world

    //接收多个参数
    def Closure3 = { 
        String str , int n -> println "$str : $n" //参数前加$
    } //也可以写作:
    def Closure3 = {
        str , n -> println "$str : $n" 
    }
    Closure3('Hello world’, 1) // 执行闭包,输出Hello world : 1

    //使用变量
    def var = "Hello world"
    def Closure4 = { 
        println var 
    } 
    Closure4() // 执行闭包,输出Hello world

    //改变上下文
    def Closure5 = {
        println Var //这时还不存在 
    }
    MyClass m = new MyClass()
    Closure5.setDelegate(m) // 改变上下文,这时Var已经有了,在执行之前改变了
    Closure5() //执行闭包,输出Hello world
    class MyClass {
        def Var = 'Hello world'
    }

4. Property

Gradle在默认情况下已经为Project定义了很多Property,如下:

    project:Project本身
    name:Project的名字
    path:Project的绝对路径
    description:Project的描述信息
    buildDir:Project构建结果存放目录
    version:Project的版本号 

通过ext来自定义Property:

    ext.property1 = "this is property1"

    或

    ext {
       property2 = "this is property2"
    }

    task showProperties << {
       println property1  //直接访问
       println property2
    }

任何实现了ExtensionAware接口的Gradle对象都可以通过这种方式来添加额外的Property,比如Task也实现了该接口。

通过“-p”命令行参数定义Property:

    task showCommandLineProperties << {
       println propertyTest
    }

    gradle -P propertyTest ="this is propertyTest" showCommandLineProperties

通过JVM系统参数定义Property(需要以“org.gradle.project”为前缀):

    gradle -D org.gradle.project.propertyTest="this is another propertyTest" showCommandLineProperties

    另一种方式:

    写入参数:gradle -DpropertyTest="this is another propertyTest"
    读取参数:def propertyTest = System.properties['propertyTest']

通过环境变量设置Property(需要以“ORG_ GRADLE_ PROJECT_ ”为前缀):

    export ORG_GRADLE_PROJECT_propertyTest = "this is yet another propertyTest"

    gradle showCommandLineProperties

5. Bean

> Groovy会为每一个字段自动生成getter和setter,我们可以通过像访问字段本身一样调用getter和setter,如:

    class GroovyBeanExample {
        private String name
    }

    def bean = new GroovyBeanExample()
    bean.name = 'this is name' //Groovy动态地为name创建了getter和setter
    println bean.name 

6. delegate机制

delegate机制可以使我们将一个闭包中的执行代码的作用对象设置成任意其他对象

    class Child {
        private String name
    }

    class Parent {
        Child child = new Child();

        void configChild(Closure c) {
            c.delegate = child
            c.setResolveStrategy Closure.DELEGATE_FIRST //默认情况下是OWNER_FIRST,即它会先查找闭包的owner(这里即parent)
            c()
        }
    }

    def parent = new Parent()
    parent.configChild {
        name = "child name"
    }

    println parent.child.name

7. task

task有两个生命周期,配置阶段和执行阶段。 
gradle在执行task时,都会先对task进行配置,task中最顶层的代码就是配置代码,在配置阶段执行,其他代码实在执行阶段执行的; 
task关键字实际上是一个方法调用,我们不用将参数放在括号里面。

    task Task1 {
        println "hello” // 这段代码是在配置阶段执行的
    }

    task Task2 {
        def name = "hello” // 这段代码是在配置阶段执行的
        doLast {
            println name  
        } // 这段代码是在执行阶段执行的,相当于:

        // doLast({
        //      println 'Hello world!'
        //  })
    }

    task Task3 << {
        println name
    }
    // “<<”语法糖,表示追加执行过程,相当于doLast,因此整个代码都是在执行阶段执行的;与之相反的是doFirst。
    //如果代码没有加“<<”,则这个任务在脚本initialization的时候执行(也就是你无论执行什么任务,这个任务都会被执行,“hello”都会被输出);
    //如果加了“<<”,则在输入命令gradle Task3后才执行

通过TaskContainer的create()方法创建Task

    tasks.create(name: 'hello') << {
        println 'hello'
    }

8. 自定义task

    class HelloWorldTask extends DefaultTask {
        @Optional
        String message = 'I am davenkin'

        @TaskAction
        def hello(){
            println "hello world $message"
        }
    }

    task hello(type:HelloWorldTask)

    task hello1(type:HelloWorldTask){
       message ="I am a programmer"
    }

@TaskAction表示该Task要执行的动作,@Optional表示在配置该Task时,message是可选的

9. 任务配置

方法一:在定义Task的时候对Property进行配置

    task hello1 << {
        description = "this is hello1"
        println description
    }

方法二:通过闭包的方式来配置一个已有的Task

    task hello2 << {
        println description
    }

    hello2 {
        description = "this is hello2"
    } //Gradle会为每一个task创建一个同名的方法,该方法接受一个闭包

    或

    hello2.description = "this is hello2"//Gradle会为每一个task创建一个同名的Property,所以可以将该Task当作Property来访问

注:对hello2的description的设置发生在定义该Task之后,在执行gradle hello2时,命令行依然可以打印出正确的“this is hello2”,这是因为Gradle在执行Task时分为两个阶段:配置阶段、执行阶段。 
所以在执行hello2之前,Gradle会扫描整个build.gradle文档,将hello2的description设置为“this is hello2”,再执行hello2。

方法三:通过Task的configure()方法完成Property的设置

    task hello3 << {
        println description
    }

    hello3.configure {
        description = "this is hello3"
    }

10. 任务依赖

    task A << {
        println 'Hello from A'
    }
    task B << {
        println 'Hello from B'
    }
    B.dependsOn A

    或

    task A << {
        println 'Hello from A'
    }
    task B {
        dependsOn A
        doLast {
            println 'Hello from B'  
        }
    }

    或

    task B(dependsOn: A) {
       println 'Hello from B'
    }

11. 顺序执行

指之间无依赖关系的任务

    task unit << {
        println 'Hello from unit tests'
    }
    task ui << {
        println 'Hello from UI tests'
    }
    task tests << {
        println 'Hello from all tests!'
    }
    task mergeReports << {
        println 'Merging test reports'
    }

    tests.dependsOn unit  //单元测试
    tests.dependsOn ui    //ui测试
    ui.mustRunAfter unit  //ui测试必须在单元测试之后执行
    tests.finalizedBy mergeReports //表示tests执行完后,再执行mergeReports,等价于mergeReports.dependsOn tests

12. 增量式构建

为一个Task定义输入(inputs)和输出(outputs),在执行该Task时,如果它的输入和输出与前一次执行时没有变化,那么Gradle便会认为该Task是最新的(日志会输出“UP-TO-DATE“),因此不会重复执行

    task combineFileContent {
       def sources = fileTree('sourceDir')
       def destination = file('destination.txt')

       inputs.dir sources        // 将sources声明为该Task的inputs
       outputs.file destination  // 将destination声明为outputs

       doLast {
          destination.withPrintWriter { writer ->
             sources.each {source ->
                writer.println source.text
             }
          }
       }
    }

当首次执行combineFileContent时,Gradle会完整地执行该Task,但是紧接着再执行一次,命令行显示:

    :combineFileContent UP-TO-DATE //被标记为UP-TO-DATE,表示该Task是最新的,不执行
    BUILD SUCCESSFUL
    Total time: 2.104 secs

如果修改inputs(上述即sourceDir文件夹)中的任何一个文件或删除destination.txt,再次调用“gradle combineFileContent”时,该Task又会重新执行

13. 自定义Plugin

在当前工程中的buildSrc/src/main/groovy/davenkin目录下创建DateAndTimePlugin.groovy文件和DateAndTimePluginExtension.groovy文件

    // DateAndTimePlugin.groovy

    package com.gradle.test

    import org.gradle.api.Plugin
    import org.gradle.api.Project

    class DateAndTimePlugin implements Plugin<Project> {
        void apply(Project project) {

            //每个Gradle的Project都维护了一个ExtenionContainer,我们可以通过project.extentions访问额外的Property和定义额外的Property
            project.extensions.create("dateAndTime", DateAndTimePluginExtension) 

            project.task('showTime') << {
                println "Current time is " + new Date().format(project.dateAndTime.timeFormat)
            }

            project.tasks.create('showDate') << {
                println "Current date is " + new Date().format(project.dateAndTime.dateFormat)
            }
        }
    }

    // DateAndTimePlugin.groovy

    package com.gradle.test

    class DateAndTimePluginExtension {
        String timeFormat = "MM/dd/yyyyHH:mm:ss.SSS"
        String dateFormat = "yyyy-MM-dd"
    }

build.gradle文件中,再apply该Plugin

    apply plugin: com.gradle.test.DateAndTimePlugin

    // 可以通过以下方式对这两个Property进行重新配置
    dateAndTime {
        timeFormat = 'HH:mm:ss.SSS'
        dateFormat = 'MM/dd/yyyy'
    }

(二)常用命令和配置

1. 编译、打包

注:执行“./gradlew xxx”等同于执行“gradle xxx”,但执行“gradle xxx”需配置环境变量

  • 清除build文件夹

    ./gradlew clean
    
  • 检查依赖并编译打包

    ./gradlew build
    
  • 编译并打Debug包

    ./gradlew assembleDebug
    
  • 编译并打Release包

    ./gradlew assembleRelease
    
  • 获取gradle版本号

    ./gradlew -v
    
  • 查看所有任务

    ./gradlew tasks 或 gradle tasks
    
  • 查看所有工程

    gradle projects
    
  • 查看所有属性

    gradle properties
    

2. 常用任务

  • 执行任务

    task A << {
        println 'Hello from A'
    }
    终端输入:gradle A
    
  • 拷贝

    task copyFile(type: Copy) {
       from 'source'
       into 'destination'
    }
    将source文件夹中的所有内容拷贝到destination文件夹中,
    这两个文件夹都是相对于当前Project而言的,即build.gradle文件所在的目录
    
  • 删除文件或文件夹

    task deleteTest(type: Delete) {
        delete 'file' ,'dir'
    }
    文件和文件夹是相对于当前Project而言的,即build.gradle文件所在的目录
    
  • 执行shell命令

    task runShell1(type: Exec) {
        executable "sh"
        args "-c", "rm ./app/libs/test.jar" //路径是相对于当前build.gradle文件
    }
    
    或者
    
    def cmd = 'date +%Y-%m-%d'
    task shellTest << {
        String date = cmd.execute().text.trim().toString() //带返回值
        print  date //打印系统日期
    }
    
  • 执行Java代码

    task runJava(type: JavaExec) {
        classpath = sourceSets.main.runtimeClasspath  //执行文件所在路径
        main = 'com.example.MyClass' // 执行方法所在类
        // arguments to pass to the application
        args 'haha','xixi' //多个参数用逗号隔开
    }
    
  • 生成jar包

    方法一:
    task deleteDes(type: Delete) {
        delete 'build/intermediates/bundles/release/class.jar', 'libs/mylib.jar'
    }
    
    task makeJar(type: Copy) {
        from('build/intermediates/bundles/release/') {
            include '*.jar' // 只拷贝jar格式的文件
        }
        into('libs')
        //include('classes.jar') // 只拷贝classes.jar这个文件
        rename('classes.jar', 'mylib.jar') // 重命名为mylib.jar
    }
    
    task releaseLib(type: Copy, dependsOn: [deleteDes, build, makeJar]) {  // 依赖多个任务
        into "../app/libs"
        from 'libs'
    }
    // 手动打包,gradle releaseLib
    
    方法二:
    // 以下是在编译流程中插入生成jar包的task
    android.libraryVariants.all { variant ->
        variant.outputs.each { output ->
            def file = output.outputFile
            def fileName = 'classes.jar'
            def name = variant.buildType.name
    
            task "makeJar${variant.name.capitalize()}" << {
                copy {
                    from("${projectDir}/build/intermediates/bundles/"+"${name}") {
                        include(fileName)
                    }
                    into(file.parent) // 可自定义存放路径
                    rename (fileName, "${project.name}"+"-${name}.jar")
                }
            }
        }
    
    }
    
    project.tasks.whenTaskAdded { task ->
        android.libraryVariants.all { variant ->
            if (task.name == "bundle${variant.name.capitalize()}") {
                task.finalizedBy "makeJar${variant.name.capitalize()}"
            }
        }
    }
    
  • 文件读取

    //以读取properties文件中保存的签名信息为例
    
    def File propFile = new File('signing.properties')
    if (propFile.canRead()) {
        def Properties props = new Properties()
        props.load(new FileInputStream(propFile))
    
        if (props != null && props.containsKey('RELEASE_STORE_FILE') && props.containsKey('RELEASE_STORE_PASSWORD') &&
                props.containsKey('RELEASE_KEY_ALIAS') && props.containsKey('RELEASE_KEY_PASSWORD')) {
    
            android.signingConfigs.release.storeFile = file(props['RELEASE_STORE_FILE'])
            android.signingConfigs.release.storePassword = props['RELEASE_STORE_PASSWORD']
            android.signingConfigs.release.keyAlias = props['RELEASE_KEY_ALIAS']
            android.signingConfigs.release.keyPassword = props['RELEASE_KEY_PASSWORD']
            println 'all good to go'
        } else {
            android.buildTypes.release.signingConfig = null
            println 'signing.properties found but some entries are missing'
        }
    } else {
        println 'signing.properties not found'
        android.buildTypes.release.signingConfig = null
    }
    

3. 常用配置

  • 设置全局参数(同额外属性设置)

    ext {
        compileSdkVersion = 22
        buildToolsVersion = "22.0.1"
    }
    
    在module中引用全局参数:
    android {
        compileSdkVersion rootProject.ext.compileSdkVersion
        buildToolsVersion rootProject.ext.buildToolsVersion
    }
    

    将属性或方法放入ext{}就可以被全局引用

  • 设置全局编码

    allprojects {
        tasks.withType(JavaCompile) {
            options.encoding = "UTF-8"
        }
    }
    
  • 设置全局编译器的版本

    allprojects {
        tasks.withType(JavaCompile) {
            sourceCompatibility = JavaVersion.VERSION_1_7
            targetCompatibility = JavaVersion.VERSION_1_7
        }
    }
    
  • 去掉重复依赖

    compile 'com.alibaba.fastjson.latest.integration' { //latest.integration 获取服务器上最新版本
        exclude module: 'annotations', group: 'com.google.android'
    }
    
  • 本地aar包依赖

    allprojects {
       repositories {
          jcenter()
          flatDir {
            dirs 'libs'
          }
       }
    }
    
    dependencies {
        compile(name:'本地库aar的名字,不带后缀', ext:'aar')
    }
    

4. java Plugin

Gradle的每个source set都包含有一个名字,并且包含有一个名为java的Property和一个名为resources的Property,他们分别用于表示该source set所包含的Java源文件集合和资源文件集合。在实际应用时,我们可以将他们设置成任何目录值,以下将资源文件按功能分包,使得与java文件分包保持一致

sourceSets {
    main {
        manifest.srcFile 'src/main/AndroidManifest.xml'
        java.srcDirs = ['src/main/java','.apt_generated']
        aidl.srcDirs = ['src/main/aidl','.apt_generated']
        assets.srcDirs = ['src/main/assets']
        res.srcDirs =
                [
                        'src/main/res/bindmobile', //绑定手机资源
                        'src/main/res/bycaptcha',  //验证码登录资源
                        'src/main/res/bypwd',      //密码登录资源
                        'src/main/res/pwdmodify',  //密码修改资源
                        'src/main/res/pwdreset',   //密码重置资源
                        'src/main/res/resource',   //其他资源
                        'src/main/res/'

                ]
    }
}

(三)配置gradle,加快编译速度

  1. ~/.gradle/gradle.properties中添加如下配置(没有该文件则新建一个):

    org.gradle.daemon=true //独立进程,停止后台进程命令:gradle --stop
    org.gradle.parallel=true //并行构建,需要将项目拆分成多个子项目,通过aar引用才能起效
    org.gradle.configureondemand=true //按需配置,目前还在试验孵化阶段,默认是关闭的
    
  2. 设置离线编译:

    打开settings->Build,Execution,Deployment->Build Tools->Gradle,
    选中Offlie Work //更新依赖包时要取消它
    
  3. 命令行构建时在命令后面加上如下参数

    --daemon 
    --parallel
    --offline
    --dry-run

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Gradle基本知识点与常用配置 的相关文章

  • android 登陆界面

    LoginActivity java package com example ruian import android app Activity import android app AlertDialog import android c
  • Android日志分析02-am篇

    Android日志分析02 am篇 在日常分析bug时 免不了和系统ActivityManagerService打交道 根据日志去查看各个Activity的生命周期 从而判断是否出现Activity生命周期异常 先使用adb logcat和
  • Android不同版本SD卡存储权限解决

    1 Android6 0之前 6 0之前是不需要动态申请权限的 直接在manifest中申请即可以正常使用
  • 基于Android系统英语学习助手APP设计开发

    一 设计思路 1 1设计目标 1 2设计思路 1 3设计内容 1 3 1界面设计 1 3 2功能模块设计 1 3 3功能流程图 1 3 4数据库设计 如果没有数据库这部分删除 1 4工具设备要求 1 5技术方案 二 设计过程与说明 2 1技
  • php如何读取解析eml文件以及生成网页的示例分享

    这篇文章主要介绍了PHP读取 解析eml文件及生成网页的方法 结合实例形式分析了PHP操作eml文件的读取 解析 转换等相关实现技巧与注意事项 并附带demo源码供读者下载参考 需要的朋友可以参考下 本文实例讲述了PHP读取 解析eml文件
  • Android Studio 无法打开虚拟机

    Emulator PANIC Cannot find AVD system path Please define ANDROID SDK ROOT 刚安装好Android Studio 却发现无法打开虚拟机 报错信息为 Emulator P
  • Android WebView使用技巧

    1 不使用WebView缓存 使用场景 通过WebView输入用户名和密码进行登录 退出登陆后 再进行登录会默认是之前输入的用户名和密码登录 那么使用如下方式可以设置webview的缓存模式 WebSettings seting web v
  • Android 版本统一管理

    前言 因为现在项目都比较模块化 组件化 要用到的model比较多 一个model就有一个build gradle文件 里面都有compileSdkVersion或buildToolsVersion等可能出现版本不一致导致编译出现错误 所以要
  • 安卓数据视图化工具SQLiteStudio

    SQLiteStudio工具使用介绍 1 下载 SQLliteStudio 解压后打开文件夹中的exe文件即可 阿里网盘有 2 对SQLliteStudio进行配置 简介 视图化安卓开发过程中数据库内容 笔者使用AndroidStudio开
  • 48、Flutter之widgets LayoutBuilder组件

    LayoutBuilder 通过 LayoutBuilder 我们可以在布局过程中拿到父组件传递的约束信息 然后我们可以根据约束信息动态的构建不同的布局 比如我们实现一个响应式的 Column 组件 ResponsiveColumn 它的功
  • Android studio 模拟器启动黑屏解决办法附图详细

    Android studio 模拟器启动黑屏解决办法附图详细 问题描述 原因分析 android模拟器在创建时 一般默认设置为热启动 所以每次关闭模拟器时 会提示保存当前运行界面状态 若选择取消 则下一次启动会以最近一次保存的状态启动显示
  • 转 使用Android Studio 创建第一个Android 应用

    转自 https blog csdn net u013926216 article details 81977815 一 使用Android Studio 开发Android 应用的流程 二 一个简单的登陆界面程序 程序功能说明 创建And
  • reactnative环境搭建-windows

    一 安装依赖 1 Node 以下为两种安装方式 1为基本安装 2为通过管理工具安装 1 按照教程步骤安装指定版本的node Node js 安装配置 注意 Node 的版本应大于等于 14 默认安装在C盘 如果自定义安装了其他盘需要配置环境
  • 开发百度地图定位APP(LBS)

    一 注册成为百度地图开发者 并获取开发密钥 获取密钥时需要进入Android studio使用keytool文件获取SHA1码 二 下载开发包解压并导入Android studio 选择自己需要的开发包下载 这里我选择的是基础地图基础定位J
  • Android Studio卸载以及安装教程

    手把手教学安卓安装 一 卸载教程 如果是第一次安装 直接看往下翻 1 先把Android Studio卸载2 将安装残余一起卸载 一定要卸载干净 否则在二次安装时会出现一大堆问题 a b c 好啦 到这里 所有的残余都已经删除干净 下面进入
  • android sdk自带的fragment标签使用

    项目开发中要用到 下面四个大分类 上面三个小分类的情况 大分类采用viewPage 小分类 使用了sdk自带的
  • Android项目中三种依赖的添加方式

    添加本地依赖 首先将所需的 jar 或者 aar 包放在libs文件夹下 方式1 右击jar包 选择Add As Library 最后sync 方式2 在app build gradle中添加本地依赖的声明 implementation f
  • 小米手机无法调试应用解决Installation failed with message Failed to establish session.

    小米手机性价比高 有些问题也很尖锐 比如我的5S用了黑科技 试验品 超声波指纹解锁 识别率就很低 每次解锁都要哈口气 真后悔 而且最近又遇到新问题 我的小米5S无法通过android studio调试应用 卖批啊 但即使这样也比蓝绿工程的O
  • Android Studio 中模拟器无法打开,提示Error launching emulator

    一 遇到的问题 运行模拟器时 提示 Error launching emulator 二 解决方法 打开SDK Manager 点击取消Android Emulator 然后重新运行 会提示下载一些文件 按着操作即可 如果没问题就不需要取消
  • 【强推荐】如何生成正式签名的APK文件

    在本篇文章您将了解到两种生成正式签名的APK文件 当然还会了解到 gradle build 与 gradle assemble 的区别 通过 Android Studio 生成 使用 Gradle 生成 文章目录 前言 使用Android

随机推荐

  • java创建自定义类的数组

    java创建自定义类的数组 错题笔记 学习动态规划做例题hdu 2602遇到的问题 创建自定义类后 新建一个自定义类的数组 向数组赋值时报如下错误 java lang NullPointerException Cannot assign f
  • 【Qt】一篇全面的信号和槽函数机制总结

    信号和槽函数机制 文章目录 信号和槽函数机制 一 信号和槽机制简介 二 信号 2 1 信号的发出 2 2 信号的处理 三 槽函数 3 1 带有默认参数的信号和槽函数 3 2 使用 QObject connect 将信号连接到槽函数的三种方法
  • integer operation result is out of range

    程序中 有如下定义 define UART1 EN 1 lt lt 31 编译后编译器报错 integer operation result is out of range 经查资料是由于溢出所致 宏定义默认常量是有符号型 当左移31位时
  • kerberos认证过程

    KDC Key Distribution Center 密钥分发中心 里面包含两个服务 AS和TGS AS Authentication Server 身份认证服务 TGS Ticket Granting Server 票据授予服务 TGT
  • [python] 使用scikit-learn工具计算文本TF-IDF值

    在文本聚类 文本分类或者比较两个文档相似程度过程中 可能会涉及到TF IDF值的计算 这里主要讲述基于Python的机器学习模块和开源工具 scikit learn 希望文章对你有所帮助 相关文章如下 python爬虫 Selenium获取
  • 铨顺宏RFID:试卷管理中RFID技术智能系统发挥着什么样的作用

    1 项目背景 在我国的教育招生考试中 试卷的管理一直是比较棘手的问题 它涉及试卷的组卷 印刷 封包 运输 发放 回收 入库 阅卷以及历史保存等一系列复杂的流程 且数量巨大 到目前为止 我国的试卷管理主要还是采取的人工管理方式 势必存在安全形
  • 随机抽奖小程序

    本实例使用随机数字生成5位抽奖号码 并显示在窗体的5个文本框中 当用户单击 开始 按钮时 将启动一个线程对象为5个文本框生成随机数字 单击 抽奖 按钮时 线程对象停止运行 并且将准确的中奖号码显示在信息文本框中 开发一个抽奖小工具的实例 1
  • 基于PaddleClas的PP-LCNet实现车辆颜色及车型属性识别

    目录 源码 yolov5源码 1 环境准备 2 数据准备 3 车辆检测
  • 目标检测评价指标合集

    目标检测评价指标 混淆矩阵 confusion matrix 可谓是贯穿了整个目标检测评价体系 衍生了一系列的目标检测评价指标 如精确率 precision 准确率 accuracy 召回率 recall F1 score ROC AUC指
  • ag-grid 学习笔记四:ag-grid方法(重设行数据、增删改、反选、新增列、插入新行、合计行接口、遍历行对象、获取置顶行数量、获取底部合计行对象、获取行对象、刷新、单元格焦点)

    一 setRowData重新设置表格行数据 重新设置表格数据很简单 只需要调用 gridOptions api setRowData 数据集 接口传入数据即可 以下函数为调用方式 function resetGrid 新的数据项 var N
  • Hackinglab(鹰眼)——基础关

    目录 1 key在哪里 2 再加密一次你就得到key啦 3 猜猜这是经过了多少次加密 4 据说MD5加密很安全 真的是么 5 种族歧视 6 HAHA浏览器 7 key究竟在哪里呢 8 key又找不到了 9 冒充登陆用户 10 比较数字大小
  • Lucene使用IK中文分词

    Lucene使用IK中文分词 环境 Lucene 6 x IKAnalyzer2012 u6 也可以通过Maven或Gradle构建工程测试和验证 对于Lucene的最新版本 需要找到IK Analyzer对应的兼容版 传送门 Lucene
  • 最新gcc下载和linux环境变量设置

    最新gcc下载和linux环境变量设置 一 gcc下载 提供最新gcc下载路径 点这里跳转 http ftp gnu org gnu gcc 安装 gcc package configure prefix usr local gcc nam
  • 前端使用代理跨域后后端无法接收Session

    将一个 MVC 项目重构为一个前后端分离项目 前端使用了 react axios vite 在前后端分离项目中 通常都会使用代理来解决跨域问题 vite 需要在 vite config js 文件中配置代理 export default d
  • hive的分组和组内排序

    背景 hive的分组和组内排序 语法 语法 row number over partition by 字段a order by 计算项b desc rank rank是排序的别名 partition by 用于给结果集分组 如果没有指定那么
  • ES内存持续增长问题分析

    环境介绍 es版本 5 6 4 Xms31g Xmx31g XX MaxDirectMemorySize 10g 问题说明 用top命令观察ES使用的物理内存不断增加到54 6G 已知堆内存31G 堆外内存MaxDirectMemorySi
  • one-class(单分类) kNN(K-Nearest Neighbor)算法Matlab实现

    one class 单分类 kNN K Nearest Neighbor 算法Matlab实现 本文的核心是给出了一个基于kNN的单分类 one class 分类器实现代码 并给出了数据以及运行实例 让读者能更好地理解并使用 代码基于MAT
  • C++解决TCP粘包

    目录 TCP粘包问题 TCP客户端 TCP服务端 源码测试 TCP粘包问题 TCP是面向连接的 面向流的可靠性传输 TCP会将多个间隔较小且数据量小的数据 合并成一个大的数据块 然后进行封包发送 这样一个数据包里就可能含有多个消息的数据 面
  • Android车载开发必备知识

    Bing Android车载开发必备知识 你好 根据搜索结果 Android车载开发必备知识是指一些关于Android系统在车载环境中的应用 测试 分发和优化的技术和方法 可以帮助开发者在车载领域开发出高效 稳定 安全和用户友好的应用 以下
  • Gradle基本知识点与常用配置

    http blog csdn net u010818425 article details 52268126 查看原文 http blog csdn net u010818425 article details 52268126 本文篇幅较