我想用 Xtend 语言编写 Java 类(仅仅是因为它更简洁),并将它编译回 Java 类,我可以在我的 Java 项目中使用这些类。就像咖啡脚本一样。我怎样才能做到这一点?
我尝试像创建一个新类一样创建一个 Xtend 文件,但是我收到此错误:
'org.eclipse.xtext.xbase.lib'
在类路径中找不到强制库包。
这会禁用智能感知(自动完成)。此外,即使我确实可以正常工作,我怎样才能将它编译为 Java 类?
在 Xtend 中,内部类使用美元符号 ('$') 取消引用,静态成员使用双冒号 ('::') 访问。
HelloAndroid 活动代码如下所示:
class XtendActivity extends Activity {
override void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R$layout::main);
}
}
尝试过同样的事情后,我可以确认启用 Xtend Nature 并添加三个 Xtend 库(前面提到过,'org.eclipse.xtext.xtend2.lib'、'org.eclipse.xtext.xbase.lib' 和 'com .google.inject') 到项目的库中至少可以编译 Xtend 代码。但是,我也遇到了 R 类的问题。
仔细检查后,看起来 R 类的问题不在于它位于不同的目录中。将文件复制到具有不同名称的主源目录不会改变任何内容。相反,看起来问题在于 R 类是一个静态最终类,包含几个静态最终子类。如果我创建一个简单的纯 Java 包装类,它将对 R.layout.main(例如)的引用包装在一个普通方法中,并从我的 Xtend 代码中调用它,那么它会接受它并愉快地编译。
在那之后,我遇到的下一个问题是Android编译器抱怨'org.eclipse.xtext.xtend2.lib'、'org.eclipse.xtext.xbase.lib'和'中有重复的about.html和plugin.properties文件com.google.inject'。通过从三个 .jar 文件中的两个中删除这些文件,这相对容易解决。我不确定它以后是否会破坏任何东西,但现在至少我有一个在 Android 模拟器上运行的 Xtend 代码的工作片段。
我只是让它编译,虽然我现在不能导入“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”的类路径元素中:
<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”文件夹中查找类文件。
到目前为止,我还没有做过任何 Android 开发。但是 Xtend 代码是针对瘦运行时库(用 Java 编写的)编译的。它主要只是三个罐子: - org.eclipse.xtext.xtend2.lib - org.eclipse.xtext.xbase.lib - com.google.collect
它们都安装在 eclipse 中,所以你应该在你安装的 plugins 文件夹中找到它们。我们通常使用 OSGI 和 PDE 将它们放在类路径中,但它实际上只是一个类路径依赖项。
Xtend 可以像 Java 一样导入类路径中的所有内容。它重用了 Java 项目配置以及 Java 开发工具。因此,只要您在类路径上有“R”类,它就可以工作。请在 bugs.eclipse.org (在 Modeling/TMF/Xtext 下)提交一个 bugzilla,如果您不能引用它,尽管您可以从 Xtend 文件旁边的 Java 中引用它。并提供一个小例子和一些额外的解释。
这是另一个问题:确保您的参数名称不与 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”,它就可以正常工作了。