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!

Android特定语言 Xtendroid的更多相关文章

  1. 在Visual Studio 2012中使用VMSDK开发领域特定语言(二)

    本文为<在Visual Studio 2012中使用VMSDK开发领域特定语言>专题文章的第二部分,在这部分内容中,将以实际应用为例,介绍开发DSL的主要步骤,包括设计.定制.调试.发布以 ...

  2. 在Visual Studio 2012中使用VMSDK开发领域特定语言(一)

    前言 本专题主要介绍在Visual Studio 2012中使用Visualization & Modeling SDK进行领域特定语言(DSL)的开发,包括两个部分的内容.在第一部分中,将对 ...

  3. Android 多语言

    Android 多语言 在res文件上右击创建新的values文件 在strings文件中设置多语言 3.在layout文件中使用 @strings/key 引用相应资源

  4. [综述]领域特定语言(Domain-Specific Language)的概念和意义

    领域特定语言(Domain Specific Language, DSL)是一种为解决特定领域问题而对某个特定领域操作和概念进行抽象的语言.领域特定语言只是针对某个特定的领域,这点与通用编程语言(Ge ...

  5. Android Init语言

    Android Init语言是一种特别简单的语言,专门用来写Android的Init进程使用的配置文件的. 相当于Linux系统中的rc文件(这句话对于Linux者多半是句废话). Android I ...

  6. 正则表达式与领域特定语言(DSL)

    如何设计一门语言(十)——正则表达式与领域特定语言(DSL) 几个月前就一直有博友关心DSL的问题,于是我想一想,我在gac.codeplex.com里面也创建了一些DSL,于是今天就来说一说这个事情 ...

  7. 在Visual Studio 2012中使用VMSDK开发领域特定语言1

    在Visual Studio 2012中使用VMSDK开发领域特定语言(一)   前言 本专题主要介绍在Visual Studio 2012中使用Visualization & Modelin ...

  8. Android各国语言对照表(values-xxx)

    eg: 阿拉伯 Arabic  SA values-ar Android各国语言对照表https://blog.csdn.net/jiangguohu1/article/details/5044014 ...

  9. Android 多语言支持

    本文内容 字符串本地化原理 环境 创建项目 测试其他语言 Android 本地化语言 ISO 编码 参考资料 使用 Android 的人越来越多,每天都在增加.因此,当你想把你的应用成功地全球化时,通 ...

随机推荐

  1. CDH建表字符集问题

    登陆metadata数据库: show variables like 'character_set%'; alter database hivemeta default character set l ...

  2. Python基础——循环语句、条件语句、函数、类

    注:运行环境  Python3 1.循环语句 (1)for循环 注:for i in range(a, b):  #从a循环至b-1 for i in range(n):      #从0循环至n-1 ...

  3. CentOS7.0 yum安装 docker

    一.安装docker 1.Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看本页面的前提条件来验证你的CentOS 版本是否支持 Docker . root 用户登录操作! 通过  ...

  4. springboot整合thymeleaf——引用静态资源

    原html src="/css/index.css" thymeleaf中,th:src="@{/css/index.css}"

  5. 利用Python进行数据分析_Pandas_基本功能

    申明:本系列文章是自己在学习<利用Python进行数据分析>这本书的过程中,为了方便后期自己巩固知识而整理. 第一 重新索引 Series的reindex方法 In [15]: obj = ...

  6. golang goroutine进行通信 channel

    1.channel的读取与声明 //goroutine之间利用channel进行通信 package main import ( "fmt" "time" ) ...

  7. 【贪心】洛谷2019 OI春令营 - 普及组 作业

    [P3817 小A的糖果 小A有N个糖果盒,第i个盒中有a[i]颗糖果. 小A每次可以从其中一盒糖果中吃掉一颗,他想知道,要让任意两个相邻的盒子中加起来都只有x颗或以下的糖果,至少得吃掉几颗糖. [贪 ...

  8. app实现长按出现弹窗 或者 出现 删除

    <!-- Kpi --> <template> <div class="kpi_container"> <nav-bar :title=& ...

  9. IntelliJ IDEA 之 配置JDK 的 4种方式

    一.新建项目前配置JDK 打开IDEA集成开发环境工具,点击:File--Project Structure,如下图 在打开的页面中,选择SDKs属性,并点击中间的加号+,选择JDK,如下图 在打开的 ...

  10. Java数据结构ArrayList

    Java数据结构ArrayList /** * <html> * <body> * <P> Copyright JasonInternational</p&g ...