我该如何在我的Android项目中使用Eclipse的新Xtend语言?

19
我想用Xtend语言编写Java类(因为它更简洁),然后将其编译回Java类中,以便在Java项目中使用。这就像coffeescript一样。 我该怎么做?
我尝试创建一个新的Xtend文件,就像创建新类一样,但是我会得到这个错误:
“classpath上找不到必需的库束'org.eclipse.xtext.xbase.lib'”。 这将禁用智能感知(自动完成)。即使我解决了这个问题,如何让它编译成Java类?
5个回答

12
在Xtend中,内部类使用美元符号("$")进行解引用,静态成员使用双冒号("::")进行访问。
HelloAndroid活动的代码如下:
class XtendActivity extends Activity {

    override void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R$layout::main);
    }
}

扶额 谢谢你!之后,这很明显。至少现在它可以编译了。但是,它仍然无法启动,因为Android在打包时包含了所有的Xtext库,并且其中有重复的文件(例如about.html)(Android APK构建器无法处理)。由于我们无法使用Maven构建Xtend,所以拆卸和重构那些JAR(仅限类)似乎是唯一的方法,对吗? - manmal
我试图从仓库中获取所有源代码,但结果发现你还必须包括 EMF 的依赖项,因为 XText 需要这些依赖项。我会等待一个更好的方法 :( - manmal
啊,这解释了很多事情。如果 Xtend 文档里有这种东西的话就更有用了。至少现在我们知道了。顺便说一句,关于那些 JAR 文件,只需将它们作为 ZIP 文件打开并删除有问题的文件即可。据我所知,这不会破坏任何东西。 - Nico de Poel
你不需要 EMF 或 Xtext jars。唯一需要的是 org.eclipse.xtext.xbase.lib、org.eclipse.xtext.xtend2.lib(两个都只包含少量类)和 google guava。不幸的是,我们仍然有一个对 google inject 的检查,实际上并不必要(我已经将其删除,所以在下一个版本中不再存在)。您可以通过在类路径上某处拥有类型 com.google.inject.Inject 来让这个检查变得顺畅。 - Sven Efftinge
@NicodePoel 我尝试过那种方式,但发现还有间接依赖项(未列在插件依赖项中),所以就放弃了。我会再试一次,像Sven建议的那样省略EMF和Xtext jars。 - manmal
@SvenEfftinge 我已经通过从JAR文件中剥离重复文件并将它们重新添加到类路径(但不是通过插件依赖项)来满足所有依赖关系。现在出现了一个错误:“在类路径上找不到必需的库包'org.eclipse.xtext.xtend2.lib'。” - 我想我需要用我的downstripped JAR文件替换Eclipse内置的JAR文件,并重新添加那些插件依赖项? - manmal

7
尝试了相同的方法后,我可以确认启用Xtend Nature并将三个Xtend库(之前提到的'org.eclipse.xtext.xtend2.lib','org.eclipse.xtext.xbase.lib'和'com.google.inject')添加到项目库中可以使Xtend代码至少编译通过。然而,我也遇到了R类的问题。
仔细检查后发现,R类的问题不在于其位于不同的目录中。将文件复制到主源目录并更改名称并没有改变任何内容。相反,问题似乎在于R类是一个静态final类,包含多个静态final子类。如果我创建一个简单的纯Java包装器类,在其中包装对R.layout.main的引用(例如)内部的普通方法,并从我的Xtend代码中调用它,则它会接受并愉快地编译。
之后,我遇到的下一个问题是Android编译器抱怨'org.eclipse.xtext.xtend2.lib','org.eclipse.xtext.xbase.lib'和'com.google.inject'中有重复的about.html和plugin.properties文件。通过从三个.jar文件中删除这些文件,可以相对容易地解决这个问题。我不确定它是否会在以后破坏任何东西,但现在至少我有一个在Android模拟器上运行的工作Xtend代码片段。

4
我刚刚编译成功,不过暂时无法导入“R”类。执行以下步骤: 首先,在Eclipse更新管理器中安装Xtend SDK,输入“http://download.eclipse.org/modeling/tmf/xtext/updates/composite/releases/”,展开节点“TMF Xtext-2.1.0”,并选择“Xtend2 SDK”。等待,然后重新启动Eclipse。 在您的Eclipse Android项目文件夹中,编辑“.project”文件(例如,在OSX终端键入“nano .project”),并更改其使其类似于这样(除了名称;您实际上可以复制整个内容并将名称改回您的项目名称):
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>TestAndroidXtend</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
    <buildCommand>
        <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
        <arguments>
        </arguments>
    </buildCommand>
    <buildCommand>
        <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
        <arguments>
        </arguments>
    </buildCommand>
    <buildCommand>
        <name>org.eclipse.jdt.core.javabuilder</name>
        <arguments>
        </arguments>
    </buildCommand>
    <buildCommand>
        <name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
        <arguments>
        </arguments>
    </buildCommand>
    <buildCommand>
        <name>com.android.ide.eclipse.adt.ApkBuilder</name>
        <arguments>
        </arguments>
    </buildCommand>
</buildSpec>
<natures>
    <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
    <nature>org.eclipse.jdt.core.javanature</nature>
    <nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
</natures>

请将以下内容插入到文件“ .classpath ”中的 classpath 元素内:

然后将以下内容插入到文件“.classpath”中的 classpath 元素内:

<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>

我把它放在了 com.android.ide.eclipse.adt.ANDROID_FRAMEWORK 的入口之前,也许你应该这么做。
回到 Eclipse,在项目上按下 F5 刷新,然后在项目的顶级目录创建一个名为 "META-INF" 的文件夹,并创建一个空文件 "MANIFEST.MF"。将以下内容粘贴到其中:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Xtend Tutorial
Bundle-SymbolicName: xtend.tutorial
Bundle-Version: 2.1.0.qualifier
Bundle-Vendor: Eclipse Modeling
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Require-Bundle: org.eclipse.xtext.xtend2.lib;bundle-version="2.0.0",
 org.junit4,
 org.aopalliance;bundle-version="1.0.0"

请在您的项目上执行“项目” -> “清理”,然后您就可以创建和使用Xtend类了。

如前所述,我无法导入R类,可能是因为Xtend只在普通的“src”文件夹中查找类文件。


你用xtend的bundle替换了原来的bundle,我想这就是为什么它停止生成R文件的原因。 - nubela
它没有停止生成文件,我无法在 .xtend 类中使用它 - 如果你问问题,请至少在猜测之前尝试答案。 - manmal

1

到目前为止,我还没有进行过任何Android开发。但是Xtend代码是针对一个轻量级的运行时库(用Java编写)进行编译的。主要只有三个JAR包: - org.eclipse.xtext.xtend2.lib - org.eclipse.xtext.xbase.lib - com.google.collect

它们都已经安装在Eclipse中,所以您应该可以在安装的插件文件夹中找到它们。我们通常使用OSGI和PDE将它们放在类路径上,但实际上它只是一个类路径依赖项。

Xtend可以像Java一样导入类路径上的所有内容。它重用Java项目配置以及Java开发工具。因此,只要您在类路径上有“R”类,它就应该可以正常工作。如果您无法引用它,尽管您可以从与Xtend文件相邻的Java中引用它,请在bugs.eclipse.org(在建模/TMF/Xtext下)上提交一个bugzilla,并提供一个小例子和一些额外的说明。


我认为你已经很清楚我可能如何实现这个目标,但是你能否提供一个更好的简明答案(逐步说明),以便我在任何Java项目中都能实现它? - nubela
@sven-efftinge:这并不容易,因为这似乎与R类的动态生成有关。没有简单的示例,因为您需要在Eclipse中安装ADT工具才能使其正常工作。 - manmal

0
另一个需要注意的地方是:确保你的参数名称与 R.java 中的任何内容不发生冲突。
我使用向导创建了一个(Java)Activity,复制了代码,删除了该 Activity,并创建了一个名为 MainActivity.xtend 的替代品,就像这样:

public class MainActivity extends Activity {

    override void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R$layout::activity_main);
    }

    override boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R$menu::activity_main, menu);
        return true;
    }

在.xtend文件中看起来很好,但由于生成的Java代码而无法构建

  public boolean onCreateOptionsMenu(final Menu menu) {
    MenuInflater _menuInflater = this.getMenuInflater();
    _menuInflater.inflate(menu.activity_main, menu);
    return true;
  }

目前不喜欢activity_main。

我花了几分钟才弄清楚“menu”参数正在覆盖R.menu.activity_main。 一旦我将.xtend的“menu”参数更改为“optionsMenu”,它就正常工作了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接