【问题标题】:Android flavor - cannot find symbol variable in R fileAndroid 风格 - 在 R 文件中找不到符号变量
【发布时间】:2015-02-03 10:43:03
【问题描述】:

我有 2 种口味 - 付费应用和免费应用。 支付应用程序的唯一区别是在MainActivity 上多了 1 个按钮,比如"paidbutton"。 付费应用有自己的布局,带有按钮android:id="@+id/paidbutton",而免费应用的布局没有这个按钮。

在代码中我使用这个:

if (BuildConfig.FLAVOR.equals("paidapp")) {
            View paidbutton = findViewById(R.id.paidbutton);
            paidbutton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    //...
                }
            });
}

但我在findViewById(R.id.paidbutton); 中有错误cannot find symbol variable

如何在不克隆两种风格的 MainActivity.java 的情况下解决这个问题?

EDIT1 - 添加更多代码示例:

分级:

productFlavors {
    paidapp {
    }
    freeapp {
    }
}

/app/src/main/res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/goNext"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Go next" />

</LinearLayout>

/app/src/paidapp/res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/goNext"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Go next" />

    <Button
        android:id="@+id/paidbutton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="See more" />


</LinearLayout>

/app/src/main/java/company/com/myapplication/MainActivity.java

package company.com.myapplication;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;


public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        View goNext = findViewById(R.id.goNext);
        goNext.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, "goNext click", Toast.LENGTH_SHORT).show();
            }
        });

        if (BuildConfig.FLAVOR.equals("paidapp")) {
            View paidbutton = findViewById(R.id.paidbutton);
            paidbutton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(MainActivity.this, "paidapp click", Toast.LENGTH_SHORT).show();
                }
            });
        }
    }

}

EDIT2 - 我找到了一些使用反射的解决方法,但仍在寻找正常的解决方案:

我用View paidbutton = findViewById(getIdFromRId("paidbutton"));代替View paidbutton = findViewById(R.id.paidbutton);

getIdFromRId 在哪里:

private int getIdFromRId(String idName) {
    int id = 0;
    try {
        Class c = R.id.class;
        Field field = c.getField(idName);
        id = field.getInt(null);
    } catch (Exception e) {
        // do nothing
    }
    return id;
}

【问题讨论】:

  • 面临同样的错误,但这似乎是预期的行为,因为当我们切换到特定的build variant(flavor) 时,会加载特定类型的资源,因此 IDE 会给出错误找不到符号。您有两个选项 1. 要么将两个按钮都放在 activity_main 中,然后使用 main 中的一个布局文件(不需要特定于风味的版本),然后在运行时根据风味的基础隐藏/显示按钮。 2. 在两种口味中复制您的MainActivity.java!

标签: android r.java-file android-productflavors


【解决方案1】:

如果您在freeapp 产品风味中根本没有paidbutton 布局元素,您可以在freeapp 产品风味文件夹中的一个资源xml 文件中声明相应的id 项。例如创建文件src/freeapp/res/values/ids.xml,其中包含:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="paidbutton" type="id"/>
</resources>

这样做之后,编译通用代码就不会出现问题,因为符号R.id.paidbutton 将为两种产品风格定义。 findViewById() 调用将在paidapp 构建中返回真正的布局元素,并在freeapp 构建中返回null。

【讨论】:

    【解决方案2】:

    你能把你的付费按钮 XML 标记和你的 MainActivity.java 类导入吗?

    您可能使用了错误的资源导入,例如 import android.R; 而不是 import my_package.R;

    【讨论】:

    • 我在导入中没有导入 R
    • 你的函数在代码中的什么位置?在 setContentView() 方法之前还是之后?编译器找不到 R 符号,因为您试图在他初始化之前使用它。
    • 编译器可以找到 R,但是在 R 文件中没有用于 freeapp 风格的 R.id.paidbutton 并且存在用于paidapp 风格的 R.id.paidbutton。这就是为什么付费应用风格组装成功但免费应用风格组装不成功的原因。
    • 好吧,在您的 Java 示例中,您没有使用正确的 R claas。添加此导入:“import company.com.myapplication.R”
    • R 文件位于与我的 MainActivity 相同的包中,因此我不需要导入它。无论如何,您的建议无济于事。
    【解决方案3】:

    您需要在 on create 中添加 if 子句,然后添加 setContentView,因此如下所示:

    if (BuildConfig.FLAVOR.equals("paidapp")) {
            setContentView(R.layout.activity_main_paid);
            View paidbutton = findViewById(R.id.paidbutton);
            paidbutton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    //...
                }
            });
    }
    else{
        setContentView(R.layout.activity_main_free);
    }
    

    或者您可以为两者使用一种布局,只是让按钮不可见

    希望对你有帮助

    【讨论】:

    • 为什么我需要activity_main_paid和activity_main_paid?我只有两种口味的activity_main
    • 这些只是不同的布局,您只使用一个 mainactivity,然后您可以在其中决定要使用的布局
    • 看起来它会起作用,但它会用不同的 sourceSets 扼杀味道的想法,我应该关心哪个 xml 将被手动而不是 androidPlugin
    猜你喜欢
    • 2015-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    相关资源
    最近更新 更多