您的位置:首页 > 移动开发 > Android开发

使用Scala编写Android程序

2013-04-06 23:00 585 查看

环境搭建:

安装JDK和Scala(本人使用2.1)

下载Android SDK,最新版本里面已经包含了Eclipse和 ADT插件
根据Eclipse版本和Scala版本下载对应的Scala IDE插件。http://download.scala-ide.org/
安装AndroidProguardScala,地址https://androidproguardscala.s3.amazonaws.com/UpdateSiteForAndroidProguardScala,安装过程可能会升级Ecplise版本,自动的。
创建Android Project
增加Scala特性,在工程的右键菜单,Scala菜单项下点击Add Scala Nature按钮
Add AndroidProguardScala Nature,
在android项目上点右键,Add AndroidProguardScala Nature

开始Android Scala之旅:

使用Scala Class重写 MainActivity。
class MainActivity extends Activity
{
override def onCreate( bundle :Bundle)
{
super.onCreate(bundle)
setContentView(R.layout.activity_main)

val btn = findViewById(R.id.button1).asInstanceOf[Button]
val txt = findViewById(R.id.editText1).asInstanceOf[EditText]
btn.setOnClickListener( new View.OnClickListener(){
def onClick( v : View)
{
txt.setText("Main Activity Using Scala.")
}
})
}
}

实例代码,模仿Java的风格,用Scala的代码重写了MainActivity类。这是使用Scala编写Android的最基本的方式,但是Scala的特性无法得到应有的发挥,这种方式编写android和使用Java几乎是一样的。下面我使用Scala的风格来重写MainActivity方法。

最简单的Scala风格,上面的实例代码中,使用的是接口来处理事件,在Scala中,一般使用函数,而不是接口。

让我在MainActivity类中增加一个隐士转换方法,后的代码。

class MainActivity extends Activity{
/*隐士转换方法*/
implicit def fun2ClickHandler( fun : View=>Unit) = new View.OnClickListener()
{
def onClick(v : View) = fun(v)

}

override def onCreate( bundle : Bundle)
{

super.onCreate(bundle);
this.setContentView(R.layout.activity_main);

val btn = findViewById(R.id.button1).asInstanceOf[Button]
val txt =  findViewById(R.id.editText1).asInstanceOf[EditText]
btn.setOnClickListener( (v :View)=>{
txt.setText("使用Scala隐士转换1")
})

}

}

上面的代码,发现,在处理Click方法时,一般都不需要使用到View参数,因此试着把该参数给去掉。后的效果

class MainActivity extends Activity{

implicit def fun2ClickHandler( fun : ()=>Unit) = new View.OnClickListener()
{
def onClick(v : View) = fun()

}

override def onCreate( bundle : Bundle)
{

super.onCreate(bundle);
this.setContentView(R.layout.activity_main);

val btn = findViewById(R.id.button1).asInstanceOf[Button]
val txt =  findViewById(R.id.editText1).asInstanceOf[EditText]
btn.setOnClickListener( ()=>{
txt.setText("使用Scala隐士转换1")
})
}
}


不过还有一点别扭,就是在设置btn.btn.setOnClickListener方法的时候多了 ()=>,如果能把这个去掉该多好,这里需要使用到Scala的传名方法,当把lambal当做函数参数时,并且该lambal函数没有接收任何参数时,可以把()给省略。进一步修改后的代码如下:

class MainActivity extends Activity{

implicit def fun2ClickHandler( fun : =>Unit) = new View.OnClickListener()
{
def onClick(v : View) = fun

}

override def onCreate( bundle : Bundle)
{

super.onCreate(bundle);
this.setContentView(R.layout.activity_main);

val btn = findViewById(R.id.button1).asInstanceOf[Button]
val txt =  findViewById(R.id.editText1).asInstanceOf[EditText]
btn.setOnClickListener( {
txt.setText("使用Scala隐士转换1")
})
}
}


btn.setOnClickListener( { txt.setText("使用Scala隐士转换1") }) 代码开起来还是有点奇怪,如果可以把()去掉,只留{...}就更完美了,还记得Scala中,如果方法只有一个参数,可以使用{}替代(),因此上面的代码btn.setOnClickListener( { txt.setText("使用Scala隐士转换1") })完全可以修改为btn.setOnClickListener { txt.setText("使用Scala隐士转换1") },自己测试吧。

 

重构,以便复用。在上面的所有代码中,隐士方法(implicit)是在MainActivity中定义的,到了其它地方就不能使用了,因此很有必要封装一个可以复用的。

可以定义一个RichButton类和其伴生类。

import android.widget.Button
import android.view.View
import android.app.Activity

class RichButton(val button : Button)
{
def onClick( handler : =>Unit)
{
button.setOnClickListener( new View.OnClickListener(){
def onClick(arg0 : View) {
handler
}

})
}

}
object RichButton
{
implicit def button2RichButton(button: Button)= new RichButton(button)
}

让后在MainActivity中,导入该类即可。

import android.app.Activity
import android.os.Bundle
import android.widget.Button
import RichButton._
import android.widget.EditText
import android.view.View
 
class MainActivity extends Activity{

override def onCreate( bundle : Bundle)
{

super.onCreate(bundle);
this.setContentView(R.layout.activity_main);

val btn = findViewById(R.id.button1).asInstanceOf[Button]
val txt =  findViewById(R.id.editText1).asInstanceOf[EditText]
btn onClick {
txt setText "button click,Using Scala By ID!!!"

}

}
}

上面的代码,应该说是非常Scala的风格了,大部分情况下,按钮都是用来设置一个事件处理方法,如果可以像

R.id.button1 onClick {
txt setText "button click,Using Scala By ID!!!"

}

这样注册事件处理方法就更完美了。想法完全可以,不过需要额外的Scala特性的支持,那就是implicit参数。

首先需要在RichButton的伴生类中增加如下方法:

implicit def button2RichButton(id : Int)(implicit cur_activity : Activity)=
{
new RichButton(cur_activity.findViewById(id).asInstanceOf[Button])
}


上面的方法定义了一个implicit参数,调用该方法的地方有一个叫cur_activity的参数。这既是个隐士方法,同时还需要用户提供隐士参数。太多隐士(implicit)了,头不要被弄晕了。

让后在Mainactivity类中,新增一个隐士变量(又来一个隐士)。

 

class MainActivity extends Activity{

implicit  var cur_activity :Activity = null
override def onCreate( bundle : Bundle)
{
cur_activity = this

super.onCreate(bundle);
this.setContentView(R.layout.activity_main);

// val btn = findViewById(R.id.button1).asInstanceOf[Button]
val txt =  findViewById(R.id.editText1).asInstanceOf[EditText]
R.id.button1 onClick {
txt setText "button click,Using Scala By ID!!!"

}

}
}

上面代码,定义了一个隐士变量implicit var cur_activity :Activity = null,并且在onCreate中对齐进行了初始化。

 

至此,已经使用了非常Scala的风格来编写android代码了。当然,很小的程序,写起来比Java的代码还多,但是随着工程的变大,使用Scala的代码量是相当少的,至于少多少,用过了就知道了。30%~50%那是很正常的。10%,说明,你还在使用Java风格来编写代码。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Scala Android