Eclipse、Android、Scala 变得简单但仍然不起作用 [英] Eclipse, Android, Scala made easy but still does not work

查看:19
本文介绍了Eclipse、Android、Scala 变得简单但仍然不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近遵循了一种使用 Scala 和 Eclipse 进行 Android 编程的方法,它减少了代码和编译时间,无需使用 Proguard 或 Treeshake.

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.

在这篇文章之后,我应该可以使用最新的 Eclipse 版本 (3.7),几乎是在模拟器版本 10 上更新的 Scala 的最新版本 (2.8.1),Eclipse 中的版本 2.8.3,带有提供的插件-

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.

提出的方法是提供一个特定的 ramdisk 镜像版本,我们可以在其中上传 Scala 库,这大大缩小了上传到模拟器的代码大小.

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.

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

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) :

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

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

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

这是 TestSinceInstallation.java 文件:

Here is the TestSinceInstallation.java file:

    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);
            }
        }
    }

这里是 ComputeSum.scala 文件

and here is the ComputeSum.scala file

    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.

推荐答案

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

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

  • 安装 Eclipse 3.7(对我来说是 3.7.2)和 Android SDK - 加上 Java SDK 7v22 如果您的系统中还没有.注意:特殊的 Android ADT Bundle 不允许安装 scala(截至 2013 年 6 月,linux 站).
  • 通过将 Eclipse 指向此网站,为 Eclipse 安装 Android ADT 插件版本 22:
  • 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).
  • Install Android ADT plug-in version 22 for Eclipse by pointing Eclipse to this website :

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

  • 通过将 Eclipse 指向此网站来安装 Scala IDE 3.0.0 版:
  • http://download.scala-ide.org/sdk/e37/scala210/stable/站点

    • 通过将 Eclipse 指向此网站来安装 AndroidProguardScala 插件 v47:
      • Install the AndroidProguardScala plug-in v47 by pointing Eclipse to this website :
      • https://androidproguardscala.s3.amazonaws.com/UpdateSiteForAndroidProguardScala

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

        Now, to create a scala project,

        1. 照常创建一个 Android 项目
        2. 右击项目,ConfigureAdd Scala nature
        3. 右击项目,添加AndroidProguardScala自然

        大功告成.

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

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

        • 惰性求值在类主体内定义视图
        • 隐式转换函数用于自定义视图与代码的交互
        • 没有分号和Scala的所有语法糖.
        • 使用actors 进行活动区分 UI 线程和处理线程.
        • 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.
        • Use of actors for activities to distinguish the UI thread from the processing thread.

        以下是其中一些示例.

        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))
        }
        

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

        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.

        // 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
          }
        }
        

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

        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项目设置为库项目,使用is作为具有不同资源的应用程序的基础,按照设置库项目的常规方法.右键单击要作为基础库项目的 Scala 项目,PropertiesAndroid,然后选中 isLibrary.
        要使用这个库创建派生项目并为其生成 APK,创建一个新的 android 项目,并且不添加任何 scala 或 androidproguardscala 性质,只需右键单击,PropertiesAndroid,并将之前的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.

        UPDATE 使用新版本的 Android Plug-in,您应该转到 Project Properties >构建路径 >订购和导出并检查Android Private Libraries.这将允许导出库项目和主项目中的 Scala 库,即使主项目没有分配 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.

        测试 使用插件 Robolectric 可以轻松测试您的 android scala 项目.只需按照创建测试项目的步骤,向其中添加 Scala 性质即可.您甚至可以使用新的 Scala 调试器,并且通过添加 scalatest 库,您可以使用 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.

        这篇关于Eclipse、Android、Scala 变得简单但仍然不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆