Xtendroid

Android特定语言
授权协议 MIT
地区 不详
投 递 者 拓拔欣嘉
软件类型 开源软件
开源组织
适用人群 未知
操作系统 Android
所属分类 程序开发、 脚本编程语言
 软件概览

Xtendroid是一款Android的领域特定语言,它大大降低样板代码,同时提供巨大的工具支持。Xtendroid利用Xtend transpiler实现,它的特点是能够在Java代码编辑或编译期间具有拓展方法和活动注释(实时编辑代码生成器)功能。活动注释,他特别能够让Xtend比Kotlin或者Groovy语言更加适合DSL的创建。Xtendroid支持的Eclipse和IntelliJ/ Android Studio,其中包括代码完成,调试等。

举例特点

Anonymous inner classes (lambdas)

Android code:

// get button widget, set onclick handler to toast a message
Button myButton = (Button) findViewById(R.id.my_button);
myButton.setOnClickListener(new View.OnClickListener() {
   public void onClick(View v) {
      Toast.makeText(this, "Hello, world!", Toast.LENGTH_LONG).show();
   }
});

Xtendroid code:

import static extension org.xtendroid.utils.AlertUtils.* // for toast(), etc.
// myButton references getMyButton(), a lazy-getter generated by @AndroidActivity
myButton.onClickListener = [View v|    // Lambda - params are optional
   toast("Hello, world!")
]

Note: Semi-colons optional, compact and differentiating lambda syntax, getters/setters as properties.

Type Inference

Android code:

// Store JSONObject results into an array of HashMaps
ArrayList<HashMap<String,JSONObject>> results = new ArrayList<HashMap<String,JSONObject>>();
HashMap<String,JsonObject> result1 = new HashMap<String,JSONObject>();
result1.put("result1", new JSONObject());
result2.put("result2", new JSONObject());
results.put(result1);
results.put(result2);

Xtendroid (Xtend) code:

var results = #[
    #{ "result1" -> new JSONObject },
    #{ "result2" -> new JSONObject }
]

Note: compact notation for Lists and Maps, method call brackets are optional

Multi-threading

Blink a button 3 times (equivalent Android code is too verbose to include here):

import static extension org.xtendroid.utils.AsyncBuilder.*
// Blink button 3 times using AsyncTask
async [
    // this is the doInBackground() code, runs in the background
    for (i : 1..3) { // number ranges, nice!
        runOnUiThread [ myButton.pressed = true ]
        Thread.sleep(250) // look ma! no try/catch!
        runOnUiThread [ myButton.pressed = false ]
        Thread.sleep(250)
    }
    return true
].then [result|
    // This is the onPostExecute() code, runs on UI thread
    if (result) {
        toast("Done!")
    }
].onError [error|
    toast("Oops! " + error.message)
].start()

Note: sneaky throws, smoother error handling. See documentation for the many other benefits to using the AsyncBuilder.

Android boilerplate removal

Creating a Parcelable in Android:

public class Student implements Parcelable {
    private String id;
    private String name;
    private String grade;
    // Constructor
    public Student(){
    }
    // Getter and setter methods
    // ... ommitted for brevity!
    // Parcelling part
    public Student(Parcel in){
        String[] data = new String[3];
        in.readStringArray(data);
        this.id = data[0];
        this.name = data[1];
        this.grade = data[2];
    }
    @Оverride
    public int describeContents(){
        return 0;
    }
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeStringArray(new String[] {this.id,
                                            this.name,
                                            this.grade});
    }
    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        public Student createFromParcel(Parcel in) {
            return new Student(in); 
        }
        public Student[] newArray(int size) {
            return new Student[size];
        }
    };
}

Xtendroid:

// @Accessors creates getters/setters, @AndroidParcelable makes it parcelable!
@Accessors @AndroidParcelable class Student {
    String id
    String name
    String grade
}

Note: the above Xtendroid code essentially generates the same Android code above, into the build/generated folder, which gets compiled normally. Full bi-directional interoperability with existing Java classes.

Functional programming

@Accessors class User {
    String username
    long salary
    int age
}
var List<User> users = getAllUsers() // from somewhere...
var result = users.filter[ age >= 40 ].maxBy[ salary ]
toast('''Top over 40 is «result.username» earning «result.salary»'''

Note: String templating, many built-in list comprehension functions, lambdas taking a single object parameter implicitly puts in scope.

Builder pattern

// Sample Builder class to create UI widgets, like Kotlin's Anko
class UiBuilder {
   def static LinearLayout linearLayout(Context it, (LinearLayout)=>void initializer) {
      new LinearLayout(it) => initializer
   }
   def static Button button(Context it, (Button)=>void initializer) {
      new Button(it) => initializer
   }
} 
// Now let's use it!
import static extension org.xtendroid.utils.AlertUtils.*
import static extension UiBuilder.*
contentView = linearLayout [
   gravity = Gravity.CENTER
   addView( button [
      text = "Say Hello!"
      onClickListener = [ 
         toast("Hello Android from Xtendroid!")
      ]
   ])
]

Note: You can create your own project-specific DSL!

Utilities

import static extension org.xtendroid.utils.AlertUtils.*
import static extension org.xtendroid.utils.TimeUtils.*
var Date yesterday = 24.hours.ago
var Date tomorrow = 24.hours.fromNow
var Date futureDate = now + 48.days + 20.hours + 2.seconds
if (futureDate - now < 24.hours) {
    confirm("Less than a day to go! Do it now?") [
        // user wants to do it now
        doIt()
    ] 
}

Note: using all of the above makes writing unit tests and instrumentation tests very easy, and fun!

 相关资料
  • 问题内容: 我用来将货币从BigDecimal格式化为字符串。按预期工作,问题在于我们的主要目标是荷兰市场,而默认的荷兰格式很奇怪。 让我解释一下,当格式化-125时,荷兰语将得到“€125-”(预期为“-€125”)。英国按预期方式提供“-£125.50”。 我可以检查语言环境是否为荷兰语,然后在每次我要设置小数格式时都提供一个模式。但是我更喜欢一个解决方案,它可以覆盖荷兰的格式设置。我在考虑以

  • 这很好,但我得到了英语的假期,我需要得到葡萄牙语。有一些参数,我可以使用它在另一种语言中获得JSON?或者那是不可能的?

  • 我正在寻找一种算法或方法,可以帮助从具有特定方言的文本语料库中识别一般短语(它来自特定领域,但对于我来说是英语方言)——例如,以下片段可能来自与世界或魔兽或MMORPHs相关的更大语料库。 玩家以第三人称或第一人称视图控制游戏世界中的角色化身,探索地形,与各种怪物战斗,完成任务,并与非玩家角色(NPC)或其他玩家互动。同样与其他MMORPG类似,《魔兽世界》要求玩家支付订阅费,或者购买预付游戏卡,

  • Gatling解析Strings参数值并将它们转换为函数,这些函数将根据存储在会话中的数据计算结果,然后对其进行评估。 加特林文件 有没有办法在exec中手动执行此操作? 我有多个使用EL属性的请求体模板,发送的请求将因进纸器而异 我目前拥有的代码如下: 我希望没有办法评估嵌套的EL属性,但是有没有办法使用会话变量手动评估它?类似于 我在其他一些问题中看到过ELCompiler被引用,但不确定从哪

  • 1 Python的函数参数传递 看两个例子: a = 1 def fun(a): a = 2 fun(a) print a # 1 a = [] def fun(a): a.append(1) fun(a) print a # [1] 所有的变量都可以理解是内存中一个对象的“引用”,或者,也可以看似c中void*的感觉。 通过id来看引用a的内存地址可以比较理解: a = 1

  • 勿在浮沙筑高台 使用这个题目,完全是向《深入浅出MFC》的侯捷致敬。 Go语言优势 可直接编译成机器码,不依赖其他库,glibc的版本有一定要求,Go 编译生成的是一个静态可执行文件,部署就是扔一个文件上去就完成了。这让部署变得异常方便,完全不需要操心应用所需的各种包、库的依赖关系,大大减轻了维护的负担。如果你是做php的,你就会知道编译一大堆的依赖是多么的繁琐,经常是你需要增加一个memcach

  • 主要内容:语法简单,并发模型,内存分配,垃圾回收,静态链接,标准库,工具链Go语言也称为 Golang,是由 Google 公司开发的一种静态强类型、编译型、并发型、并具有垃圾回收功能的编程语言。 接下来从几个方面来具体介绍一下Go语言的特性。 语法简单 抛开语法样式不谈,单就类型和规则而言,Go 与 C99、C11 相似之处颇多,这也是Go语言被冠以“NextC”名号的重要原因。 Go语言的语法处于简单和复杂的两极。C语言简单到你每写下一行代码,都能在脑中想象出编译后

  • 介绍 语言特性,即lang包,主要针对JDK中的一些数据结构和接口的完善,包括: caller 获取方法调用者 copier 复制器抽象接口 func 函数接口 hash 哈希算法 loader 加载器抽象接口 mutable 提供可变对象 tree 提供树状结构 其它 总之,lang包下提供了一个大杂烩,汇集了各种数据结构。