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. navicat-use

    https://blog.csdn.net/weixin_44496987/article/details/87186071

  2. Excel关联匹配函数

    1.=VLOOKUP (lookup_value, table_array, col_index_num, [range_lookup]) ​ lookup_value 相当于python中的键,用来 ...

  3. python学习-50 pickle模块

    pickle模块 与json方法是一样的 import pickle dic = {'} print(type(dic)) a = pickle.dumps(dic) print(type(a)) f ...

  4. 1.ASP.NET Core Docker学习-Docker介绍与目录

    Docker的优点: 1节约时间,快速部署和启动 2节约成本 3标准化应用发布 4方便做持续集成 5可以用Docker做为集群中的轻量主机或节点 6方便构建基于SOA或者微服务架构 的系统 学习目录: ...

  5. 无服务架构在IOT的应用场景——使用函数工作流处理DIS数据

    在物联网领域,复杂性往往并非在于传感器,真正的复杂性在于各种传感器产生的大量数据,以及对这些数据的处理,所以开发者不得不花费大量的时间去构建和维护后端服务器来处理这样一个庞大的数据流.而在今天这个敏捷 ...

  6. Istio技术与实践03:最佳实践之sidecar自动注入

    Istio通过对serviceMesh中的每个pod注入sidecar,来实现无侵入式的服务治理能力.其中,sidecar的注入是其能力实现的重要一环(本文主要介绍在kubernetes集群中的注入方 ...

  7. (二)Activiti之用activiti.cfg.xml配置文件初始化表

    一.案例 本章案例使用activiti 5.19.0.2版本 1.1 引入maven依赖 <dependencies> <dependency> <groupId> ...

  8. IE浏览器 Table 兼容问题

    border篇: 直接在<tr>标签上添加 border-bottom:1px solid red;  在IE8以上浏览器有效,IE7以下版本无效   解决方案:需给<table&g ...

  9. Html5+Mui前端框架,开发记录(三):七牛云 上传图片

    1.Html界面: <div id="container"> <label>凭证:</label> <div id="uploa ...

  10. ASP.NET Core 中的脚本标记帮助程序

    官网地址:https://docs.microsoft.com/zh-cn/aspnet/core/mvc/views/tag-helpers/built-in/script-tag-helper?v ...