在 Android Studio 中更改 xml 布局文件后需要重建

Posted

技术标签:

【中文标题】在 Android Studio 中更改 xml 布局文件后需要重建【英文标题】:Rebuild required after changing xml layout files in Android Studio 【发布时间】:2015-11-25 21:01:40 【问题描述】:

我正在开发 android 应用程序,我正在使用 Android Studio。

虽然有问题。当我更改 source 并运行应用程序时,它可以正常工作,但是当我更改 资源 时,它不会改变,直到我执行 Clean Project。例如我添加了一个按钮并运行该应用程序,该按钮不存在,但是当我执行一个干净的项目时,它就在那里。 Android studio 在访问新添加视图的id 时显示错误。

请帮我解决这个问题。任何帮助将不胜感激。

附加信息: -Android Studio 版本:1.3.1 -操作系统:windows -Gradle 版本:2.6

编辑:

我有多个目录作为我的 gradle 资源,如下所示:

sourceSets
     main  
         manifest.srcFile 'src/main/AndroidManifest.xml'
         java.srcDirs = ['src/main/java', '.apt_generated']
         aidl.srcDirs = ['src/main/aidl', '.apt_generated']
         res.srcDirs = [
            'src/main/res',
            'src/main/res/layouts/test',
            'src/main/res/layouts/login',
            'src/main/res/layouts/main',
            'src/main/res/layouts/includes'
        ]
    

当我尝试以更改的布局运行项目时,它会说:

No apk changes detected. Skipping file upload, force stopping package instead. DEVICE SHELL COMMAND: am force-stop com.my.package

【问题讨论】:

Android studio shows an error when accessing the id of the newly added view ... 错误是什么? @FrankN.Stein 因为找不到 id 而变成红色 可能是bug?更改布局后尝试切换到 java-file。并通过 Ctrl-S 重新保存 java 文件。这必须比项目清理更快 我会尝试添加更多信息。 我也有同样的问题。我正在使用 v1.3.2 并且从 v1.3.0 开始就遇到了这个问题。我在 Ubuntu 上。似乎 gradle 任务发生了变化,以某种方式跳过了构建更改的文件。 【参考方案1】:

我通过不使用嵌套资源文件夹解决了我的问题。我有多个资源文件夹。解决方法是在 res 文件夹旁边而不是在其中创建其他资源文件夹。我的 gradle 变化如下:

sourceSets
     main  
         manifest.srcFile 'src/main/AndroidManifest.xml'
         java.srcDirs = ['src/main/java', '.apt_generated']
         aidl.srcDirs = ['src/main/aidl', '.apt_generated']
         res.srcDirs = [
            'src/main/res',
            'src/main/test',
            'src/main/login',
            'src/main/main',
            'src/main/includes'
        ]
    

其他资源文件夹中的所有更改现在无需清理和重建项目即可生效。希望对你有帮助。

【讨论】:

工作,谢谢。为每个资源组添加 res- 前缀会使结构看起来很漂亮。 在我的情况下不起作用,我正在为同一个应用程序创建 35 种不同的风格,以下答案中的解决方案就像一个魅力。 在添加 TrevJonez 的答案时,我已经想出了这个解决方案,它对我有用。所以我没有测试那个解决方案。你可以自己测试一下。 @CoolMind 您现在是否使用将资源分离到子文件夹中?对我来说这很有趣,但我必须按 Build > Rebuild Project。 @TrevJonez 的解决方案并没有改变我的这种行为。 它对我有用。非常感谢。我不知道为什么那个建立了如此糟糕的项目并且没有解决这个问题并离开的人......这浪费了我一天。再次感谢您。【参考方案2】:

这是一种更新的方法,无论风味配置如何,都能获得相同的效果:

android.applicationVariants.all  variant ->
  tasks.named("generate$variant.name.capitalize()Resources").configure  mergeResourceTask ->
    mergeResourceTask.outputs.upToDateWhen  false 
  
  tasks.named("merge$variant.name.capitalize()Resources").configure  mergeResourceTask ->
    mergeResourceTask.outputs.upToDateWhen  false 
  

对于根本问题,这仍然是一个绝对糟糕的解决方法。它消除了任何最新的或任务输出缓存,否则这些缓存会使您的非资源更改构建更快地跳过这些任务。

正确的解决方法是公认的答案,即不使用嵌套资源目录,因为 android gradle 插件最初旨在支持。通过不嵌套任务输入,应在将目录添加到源集时正确声明,并且 gradle 将正确确定何时运行任务。

如果您仍想嵌套资源目录,请通读此自述文件:https://github.com/davebren/ResourceNestingExample 具体而言:The quirk is that you can't declare a container resource folder before you declare that folder's child resource folders.

我原来的回答:

这是一个 hacky 和低效的解决方法。

在你的 module_dir/build.gradle 添加以下代码。

afterEvaluate 
  def flavors = []
  def types = []

  android.applicationVariants.all  variant ->
    def flyp = variant.name.split("(?=\\pUpper)")
    if (!flavors.contains(flyp[0]))
    
        flavors.add(flyp[0])
    
    if (!types.contains(flyp[1]))
    
        types.add(flyp[1])
    
  

  tasks.all  Task task ->

    for (String fl : flavors)
    
      for (String ype : types)
        
            if (task.name.contains("generate$fl.capitalize()$ype.capitalize()Resources") || 
                task.name.contains("merge$fl.capitalize()$ype.capitalize()Resources"))
            
                task.outputs.upToDateWhen  false 
            
        
    

这将使 gradle 构建重新生成并合并每个构建的资源。在三层深的循环之上,增量生成的损失使这成为一个可怕的代码块。

在我的项目中使用单个 java 行添加它之前,在 ~31 秒内更改了构建,在添加后 ~35 秒。

希望他们尽快修复插件。

【讨论】:

这是为使用风格和类型的 android 应用程序设置的。如果它是一个库,你会得到不同的变体名称。如果您不使用风味,您可以跳过整个顶部并直接在任务循环中引用android.applicationVariants.all @CoolMind 如果您仍想嵌套您的目录,我添加了一个带有资源嵌套示例的 github 链接。还更新了 gradle groovy dsl 示例以直接使用 android 变体,而不是尝试对笛卡尔坐标进行逆向工程。自原始答案以来的几年里学到了很多东西:) 您应该尽快更新到最新的 Gradle。命名用于惰性任务配置。 @TrevJonez,谢谢!你知道,在将 AS 升级到 3.2 之后,情况发生了变化。当我将新布局(或可绘制)从res/layout 移动到另一个文件夹时,它的第一个标签带有红色下划线,在其他布局或代码中它不可见。现在重建没有帮助,只有 Invalidate > Restart and invalidate cache. 我们也可以清除之前的对话,我删除了我的记录。【参考方案3】:

解决方案是不要嵌套资源目录。将所有布局保存在 /res/layout/ 文件夹下。您可以使用一些前缀来缩短它们,例如 test_xxxx 或 login_xxxx。

无论如何,出于某种原因,Gradle 仅在进行增量构建时才计算布局主目录中的更改。在您对项目进行干净和完整的重建之前,不会注意到任何其他子文件夹中的更改。

如果有人知道如何包含资源子文件夹并同时避免该问题,请告诉我...

【讨论】:

Please use Answers exclusively to answer the question。您应该edit您的答案以删除后续问题。如果您愿意,可以将其作为一个单独的新问题发布。【参考方案4】:

首先,谢谢上面的 Saeed Enterzari。

其次,我们应该关心这个: 'res.srcDirs' 中的那些 res scr 目录应该存在,否则,每次更改 xml 文件时都必须重新构建项目。

这是 Saeed Enterzari 所说的,但我们可以简单地说。

sourceSets
     main  
         manifest.srcFile 'src/main/AndroidManifest.xml'
         java.srcDirs = ['src/main/java', '.apt_generated']
         aidl.srcDirs = ['src/main/aidl', '.apt_generated']
         res.srcDirs = [
            'src/main/res',
            'src/main/test',
            'src/main/login',
            'src/main/main',
            'src/main/includes'
        ]
    

之后

sourceSets 
    main 
        jniLibs.srcDirs = ['libs'] 
        res.srcDirs = ['src/main/res']
    

【讨论】:

【参考方案5】:

Gradle:6.5,Android Gradle 插件:4.1.2 上面使用源集的解决方案不起作用。我根据https://developer.android.com/studio/build/build-variants改了口味

即:

android
    flavorDimensions  'system' , 'subtype'
    productFlavors 

        fl1 
            dimension 'system'
        

        fl2 
            dimension 'system'
        

        fl2sub 
            dimension 'subtype'
        

        fl1service 
            dimension 'subtype'
        

        fl1production 
            dimension 'subtype'
        
    
    // Remove redundant build variants
    variantFilter  variant ->
        def names = variant.flavors*.name
        if (names.contains("fl1") && names.contains("fl2")) 
            variant.ignore = true
        
    

【讨论】:

以上是关于在 Android Studio 中更改 xml 布局文件后需要重建的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Android Studio 在编辑 xml 文件或更改设计时会变慢?

更改 android studio 中的 textview 样式

在 Android Studio 中更改项目主题?

android studio怎么更改应用的名字

如何在android studio中更改包名? [复制]

如何在 android studio 中使用 AppCompat 类更改通知栏的颜色?