38 votes

Eclipse, Android, Scala simplifié mais ne fonctionne toujours pas

J'ai récemment suivi une voie de la programmation pour Android à l'aide de Scala et d'Eclipse qui réduit le code et le temps de compilation sans utiliser Proguard ou Treeshake.

En suivant cet article, je devrais pouvoir utiliser la dernière version d'Eclipse (3.7), presque la dernière version de Scala (2.8.1) mise à jour sur un émulateur version 10, la version 2.8.3 dans Eclipse avec le plug-in fourni.

La solution proposée consiste à fournir une version spécifique de l'image du ramdisk, dans laquelle nous pouvons télécharger les bibliothèques scala, ce qui réduit considérablement la taille du code à télécharger vers l'émulateur.

J'ai suivi les étapes, créé un hello world, ajouté la nature scala, ajouté une classe scala factice, déplacé le constructeur Scala avant l'installateur de paquets Android, tout se construit parfaitement, mais quand je lance l'apk sur un émulateur depuis Eclipse, l'application plante et j'obtiens l'erreur suivante, qui ressemble à la suivante la même que celle présentée ici (à la fin du document) :

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

Si je supprime la référence à scala dans le fichier d'activité, tout se passe bien.

Voici le fichier 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);
            }
        }
    }

et voici le fichier ComputeSum.scala

    package upg.TestSinceInstallation

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

Que pensez-vous que je doive faire pour que cela fonctionne ? Je me sens si proche du but.

56voto

Mikaël Mayer Points 2408

Voici la solution, pour utiliser Android avec Eclipse 3.7 et avec Scala 3.0.0 sans aucun problème.

  • Installer Eclipse 3.7 (pour moi 3.7.2) et l'option SDK Android - plus le Java SDK 7v22 s'il n'est pas déjà présent dans votre système. Attention : L'ADT Bundle spécial Android ne permet pas d'installer scala (à partir de juin 2013, station linux) .
  • Installez le plug-in Android ADT version 22 pour Eclipse en pointant Eclipse vers ce site web :

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

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

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

Maintenant, nous allons créer un projet scala,

  1. Créez un projet Android comme d'habitude
  2. Cliquez avec le bouton droit de la souris sur le projet, Configure , Add Scala nature
  3. Cliquez avec le bouton droit de la souris sur le projet, Add AndroidProguardScala nature

Vous avez terminé.


Scalafier le code d'Android

Maintenant, de bonnes choses se produisent. Tout d'abord, vous pouvez scalafy n'importe quelle activité, et vous aurez accès aux fonctionnalités uniques de scala, telles que :

  • Évaluations paresseuses pour définir des vues à l'intérieur du corps de la classe
  • Fonctions de conversion implicites pour personnaliser l'interaction de la vue avec votre code
  • Pas de point-virgule et tout le sucre syntaxique de scala.
  • Utilisation de acteurs pour les activités pour distinguer le fil d'exécution de l'interface utilisateur du fil d'exécution du traitement.

Voici un exemple de certains d'entre eux.

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

Après tout ce qui précède, il est très utile de rédiger des activités concises. Notez que nous pouvons opérer directement sur les identifiants comme s'il s'agissait de vues. La désambiguïsation est nécessaire car (view: TextView).requestFocus() si les méthodes peuvent être déduites de diverses 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
  }
}

Assurez-vous que le nom du fichier scala correspond à l'activité principale qu'il contient. MyActivity.scala .

Deuxièmement, pour configurer un projet scala en tant que projet de bibliothèque, afin de l'utiliser comme base pour des applications disposant de ressources différentes, suivez la procédure suivante la mise en place régulière d'un projet de bibliothèque . Cliquez avec le bouton droit de la souris sur le projet scala que vous souhaitez utiliser comme projet de bibliothèque de base, Properties , Android et vérifier isLibrary .
Pour créer un projet dérivé utilisant cette bibliothèque et pour lequel vous pouvez générer un APK, créez un nouveau projet Android, et sans ajouter de nature scala ou androidproguardscala, faites un clic droit, Properties , Android et ajoutez le projet scala précédent en tant que bibliothèque.

MISE À JOUR Avec la nouvelle version du plug-in Android, vous devez vous rendre à l'adresse suivante Project Properties > Build Päth > Order and Export et vérifier Android Private Libraries . Cela permettra d'exporter la bibliothèque Scala, à la fois dans le projet de bibliothèque et dans le projet principal, même si le projet principal n'est pas affecté à Scala.

TEST Utilisation du plug-in Robotique permet de tester facilement votre projet scala Android. Il suffit de suivre les étapes de création d'un projet de test et d'y ajouter la nature Scala. Vous pouvez même utiliser le nouveau débogueur Scala, et en ajoutant l'option le plus grand nombre vous pouvez utiliser les filtres de correspondance et bien d'autres fonctionnalités de Scala.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X