I recently followed a way of programming for Android using Scala and Eclipse, which reduces the code and the compile time without using Proguard or Treeshake.

我最近采用了一种使用Scala和Eclipse进行Android编程的方法,它可以在不使用Proguard或Treeshake的情况下减少代码和编译时间。

Following this article, I should be able use the last Eclipse build (3.7), almost the last version of Scala (2.8.1) updated on an emulator version 10, the version 2.8.3 within Eclipse with the provided plug-in.

在本文之后,我应该能够使用上一个Eclipse构建(3.7),几乎是在仿真器版本10上更新的Scala(2.8.1)的最新版本,Eclipse中的版本2.8.3以及提供的插件。

The presented way is to provide a specific ramdisk image version, where we can upload scala libraries, which drastically shrinks the size of the code to upload to the emulator.

提供的方法是提供特定的ramdisk映像版本,我们可以在其中上传scala库,这会大大缩小要上传到模拟器的代码的大小。

I followed the steps, created a hello world, added scala nature, added a dummy scala class, moved the Scala builder before the Android Package Installer, everything builds perfectly, but when I launch the apk on a emulator from Eclipse, the application crashes and I get the following error, which looks like the same as presented here (at the end of the document) :

我按照步骤,创建了一个hello world,添加了scala本质,添加了一个虚拟scala类,在Android Package Installer之前移动了Scala构建器,一切都构建完美,但是当我在Eclipse的模拟器上启动apk时,应用程序崩溃了我收到以下错误,看起来与此处提供的相同(在文档末尾):

    03-29 10:29:38.505: E/AndroidRuntime(839): java.lang.NoClassDefFoundError: upg.TestSinceInstallation.ComputeSum

If I remove the scala reference in the activity file, it runs well.

如果我删除活动文件中的scala引用,它运行良好。

Here is the TestSinceInstallation.java file:

这是TestSinceInstallation.java文件:

    package upg.TestSinceInstallation;

    import android.app.Activity;
    import android.os.Bundle;
    import upg.TestSinceInstallation.ComputeSum;

    public class TestSinceInstallationActivity extends Activity {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            int a = 1;
            int b = 5;
            ComputeSum cs = new ComputeSum(a, b);
            if(cs.getResut() == 6) {
              setContentView(R.layout.main);
            }
        }
    }

and here is the ComputeSum.scala file

这是ComputeSum.scala文件

    package upg.TestSinceInstallation

    class ComputeSum(a: Int, b: Int) {
      def getResut() : Int = a + b
    }

What do you think I should do to make this work ? I feel so close to the goal.

您认为我应该怎么做才能使这项工作成功?我感觉如此接近目标。

1 个解决方案

#1


55

Here is the solution, to use Android with Eclipse 3.7 and with Scala 3.0.0 without any problems.

这是解决方案,使用Android与Eclipse 3.7和Scala 3.0.0没有任何问题。

  • Install Eclipse 3.7 (for me 3.7.2) and the Android SDK - plus the Java SDK 7v22 if not already in your system. Caution: The special Android ADT Bundle does not allow to install scala (as of June 2013, linux station).
  • 安装Eclipse 3.7(对我来说是3.7.2)和Android SDK - 加上Java SDK 7v22(如果你的系统中还没有)。注意:特殊的Android ADT Bundle不允许安装scala(截至2013年6月,linux工作站)。
  • Install Android ADT plug-in version 22 for Eclipse by pointing Eclipse to this website :
  • 通过将Eclipse指向此网站,为Eclipse安装Android ADT插件版本22:

https://dl-ssl.google.com/android/eclipse/

https://dl-ssl.google.com/android/eclipse/

  • Install Scala IDE version 3.0.0 by pointing Eclipse to this website :
  • 通过将Eclipse指向此网站来安装Scala IDE 3.0.0版:

http://download.scala-ide.org/sdk/e37/scala210/stable/site

http://download.scala-ide.org/sdk/e37/scala210/stable/site

  • Install the AndroidProguardScala plug-in v47 by pointing Eclipse to this website :
  • 通过将Eclipse指向此网站来安装AndroidProguardScala插件v47:

https://androidproguardscala.s3.amazonaws.com/UpdateSiteForAndroidProguardScala

https://androidproguardscala.s3.amazonaws.com/UpdateSiteForAndroidProguardScala

Now, to create a scala project,

现在,要创建一个scala项目,

  1. Create an Android project as usual
  2. 像往常一样创建一个Android项目
  3. Right-click on the project, Configure, Add Scala nature
  4. 右键单击项目,配置,添加Scala特性
  5. Right-click on the project, Add AndroidProguardScala nature
  6. 右键单击该项目,添加AndroidProguardScala性质

You're done.

你完成了。


Scalafying android code

Now good things happen. First, you can scalafy any activity, and you will get access to scala unique features, such as:

现在好事发生了。首先,您可以对任何活动进行scalafy,您将可以访问scala的独特功能,例如:

  • Lazy evaluations to define views inside the class body
  • 延迟评估以定义类体内的视图
  • Implicit conversion functions to customize the interaction of view with your code
  • 隐式转换函数用于自定义视图与代码的交互
  • No semicolons and all the syntactic sugar of scala.
  • 没有分号和scala的所有语法糖。
  • Use of actors for activities to distinguish the UI thread from the processing thread.
  • 使用actor进行活动以区分UI线程和处理线程。

Here is an example of some of them.

以下是其中一些示例。

package com.example.testing;
import android.app.Activity
import android.os.Bundle
import scala.collection.mutable.Map
import android.view.View
import android.widget.SeekBar
import android.widget.ImageButton
import android.graphics.drawable.Drawable
import android.widget.TextView

trait ActivityUtil extends Activity {
  implicit def func2OnClickListener(func: (View) => Unit):View.OnClickListener = {
    new View.OnClickListener() { override def onClick(v: View) = func(v) }
  }
  implicit def func2OnClickListener(code: () => Unit):View.OnClickListener = {
    new View.OnClickListener() { override def onClick(v: View) = code() }
  }
  private var customOnPause: () => Unit = null
  override def onPause() = {
    super.onPause()
    if(customOnPause != null) customOnPause()
  }
  def onPause(f: =>Unit) = {
    customOnPause = {() => f}
  }
  private var customOnCreate: Bundle => Unit = null
  override def onCreate(savedInstanceState: Bundle) {
    super.onCreate(savedInstanceState)
    if(customOnCreate != null) customOnCreate(savedInstanceState)
  }
  def onCreate(f: Bundle => Unit) = {
    customOnCreate = f
  }
  // Keep references alive when fetched for the first time.
  private implicit val vMap = Map[Int, View]()
  private implicit val ibMap = Map[Int, ImageButton]()
  private implicit val sbMap = Map[Int, SeekBar]()
  private implicit val tvMap = Map[Int, TextView]()
  private implicit val dMap = Map[Int, Drawable]()

  def findView[A <: View](id: Int)(implicit v: Map[Int, A]): A = v.getOrElseUpdate(id, findViewById(id).asInstanceOf[A])
  def findDrawable[A <: Drawable](id: Int)(implicit v: Map[Int, A]): A = v.getOrElseUpdate(id, getResources().getDrawable(id).asInstanceOf[A])

  implicit class RichView(b: View) { // Scala 2.10 !
    def onClicked(f: =>Unit) = b.setOnClickListener{ () => f }
  }
  // Implicit functions to operate directly on integers generated by android.
  implicit def findViewImageButton(id: Int): ImageButton = findView[ImageButton](id)
  implicit def findViewSeekBar(id: Int): SeekBar = findView[SeekBar](id)
  implicit def findViewTextView(id: Int): TextView = findView[TextView](id)
  implicit def findDrawable(id: Int): Drawable = findDrawable[Drawable](id)
  implicit def findRichView(id: Int): RichView = toRichView(findView[View](id))
}

Now after all the previous boilerplate, it is very useful to write concise activities. Note how we can directly operate on ids as if they were views. Disambiguation is needed as (view: TextView).requestFocus() if the methods can be inferred from various structures.

现在,在所有以前的样板之后,编写简洁的活动非常有用。请注意我们如何直接对id进行操作,就好像它们是视图一样。如果可以从各种结构推断出方法,则需要消除歧义(view:TextView).requestFocus()。

// Now after all the boilerplate, it is very useful to write consise activities
class MyActivity extends Activity with ActivityUtil {
  import R.id._ // Contains R.id.button, R.id.button2, R.id.button3, R.id.mytextview
  lazy val my_button: ImageButton = button   //In reality, R.id.button
  lazy val his_button: ImageButton = button2

  onCreate { savedInstanceState =>       // The type is automatically inferred.
    setContentView(R.layout.main)
    my_button.setOnClickListener(myCustomReactClick _)
    his_button.setOnClickListener { () =>
       //.... Scala code called after clicking his_button
    }
    button3.onClicked {
      // Awesome way of setting a method. Thanks Scala.
    }
    mytextview.setText("My text")  // Whoaaa ! setText on an integer.
    (mytextview: TextView).requestFocus() // Disambiguation because the method is ambiguous
    // Note that because of the use of maps, the textview is not recomputed.
  }

  def myCustomReactClick(v: View) = {
    // .... Scala code called after clicking my_button
  }
  onPause{
    // ... Custom code for onPause
  }
}

Make sure that the name of the scala file matches the main activity contained in it, in this case it should be MyActivity.scala.

确保scala文件的名称与其中包含的主要活动匹配,在这种情况下,它应该是MyActivity.scala。

Second, to set up a scala project as a library project, to use is as a base for applications having different resources, follow the regular way of setting up a library project. Right-click on the scala project that you want as a base library project, Properties, Android, and check isLibrary.
To create derivated project using this library and for which you can generate an APK, create a new android project, and without adding any scala or androidproguardscala nature, just right-click, Properties, Android, and add the previous scala project as a library.

其次,要将scala项目设置为库项目,使用它作为具有不同资源的应用程序的基础,遵循常规方式设置库项目。右键单击要作为基础库项目的scala项目,属性,Android和检查isLibrary。要使用此库创建派生项目并为其生成APK,请创建一个新的android项目,而不添加任何scala或androidproguardscala性质,只需右键单击,属性,Android,并将以前的scala项目添加为库。

UPDATE With the new version of the Android Plug-in, you should go to Project Properties > Build Päth > Order and Export and check Android Private Libraries. This will allow to export the scala library, both in the library project and the main project, even if the main project is not assigned Scala.

更新使用新版Android插件,您应该转到Project Properties>BuildPäth> Order and Export并检查Android Private Libraries。这将允许导出库项目和主项目中的scala库,即使主项目未分配Scala也是如此。

TESTING Using the plug-in Robolectric makes it easy to test your android scala project. Just follow the steps for creating a test project, add Scala nature to it. You can even use the new scala debugger, and by adding the scalatest library, you can use should matchers and many other features Scala has.

测试使用插件Robolectric可以轻松测试你的android scala项目。只需按照创建测试项目的步骤,添加Scala特性。您甚至可以使用新的scala调试器,通过添加scalatest库,您可以使用Scala和Scala的许多其他功能。

更多相关文章

  1. Android Studio 项目的导入以及依赖
  2. 从零开始的Android新项目2 - Gradle篇
  3. 使用Android库项目设置ProGuard
  4. android studio如何把本地项目上传到git@osc
  5. Libgdx设置UI在新GWT项目中出现2个意外错误
  6. android插件化-apkplug中以监听方式获取OSGI服务-09
  7. 将不同的Android项目连接到现有的Google-Endpoints后端
  8. 如何将Maven添加到现有的IntelliJ Android项目中
  9. Thrift项目Server端开发流程

随机推荐

  1. Javascript函数的4种调用方法详解
  2. React.js中的setState vs replaceState
  3. 选择无线电输入时,无法提交带有JavaScript
  4. 【JavaScript】中两个小括号 ()() 是什么
  5. jQuery的几大难点
  6. 利用javascript实现遍历xml文件的代码实
  7. 一个html+css+js的轮播图片 -- 仅供参考
  8. 输入自动完成或Rails中的新功能
  9. Jquery中动态添加元素的绑定事件不起作用
  10. jqGrid 数据加载完事件 loadComplete 使