2013-03-03 28 views
3

我有一个Java Android应用程序,我想更改为Scala。我有很多片段,我想知道在Scala中做什么是最好的方法。基于Java的Android应用程序 - >切换到Scala

这是我的Java片段类MyFragment

public class MyFragment extends Fragment { 
    private WebView myWebView; 
    private TextView myTextView; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 
     View myView = inflater.inflate(R.layout.my_view, container, false); 
     myWebView = (WebView) myView.findViewById(R.id.my_webview); 
     myWebView.loadUrl("http://www.google.com/"); 
     myTextView = (TextView) myView.findViewById(R.id.my_textview); 
     myTextView.setText("Google.com"); 
     return myView; 
    } 
} 

我一直有这样的基本结构:这是我在onCreateView实例一些私人的UI元素,做一些事情,并返回视图(这里没有显示:在其他on*方法我也对UI元素做了一些操作)。

我发现一些文章做了lazy val像这里描述:http://blog.andresteingress.com/2011/09/20/programming-android-with-scala/ 但在我的情况下,这是行不通的,因为我有片段而不是活动。首先,我必须夸大主视图myView,然后我可以获取它的UI元素。

在Scala中做这件事的最好方法是什么?

--- UPDATE ---

我的Scala代码看起来像这样的时刻:

class MyFragment extends Fragment { 
    private var myTextView: TextView = null 

    override def onCreateView(inflater: LayoutInflater, 
    container: ViewGroup, savedInstanceState: Bundle): View = { 
     val myView = inflater.inflate(R.layout.my_view, container, false) 
     val myWebView = myView.findViewById(R.id.my_webview).asInstanceOf[WebView] 
     myWebView.loadUrl("http://www.google.com/") 
     myTextView = myView.findViewById(R.id.my_textview).asInstanceOf[TextView] 
     myTextView.setText("Google.com") 
     myView 
    } 
} 

所以,你可以在这里我改进? myTextViewprivate var,因为我必须在这个片段中访问它几种方法。看来我不能做这里解释的东西:http://blog.andresteingress.com/2011/09/20/programming-android-with-scala/lazy valTypedActivityOnClickListener的隐式转换,因为我使用片段。那么我怎样才能摆脱.asInstanceOf[T]的样板代码,并使其更像斯卡拉?

回答

4

基于更新的代码,我只能做一些建议,以更“斯卡拉十岁上下的”


使用Option而不是null您的会员

private var myWebView: Option[WebView] = None 
private var myTextView: Option[TextView] = None 

为了避免在代码中明确地转换你的视图,你需要将它移动到其他地方,但是你不能摆脱它,因为原始的android API并没有给你提供任何有关运行时或共享的线索返回对象的mpiletime类型。为了解决这个问题,你提到的帖子使用了定制的类型化资源和一个处理这些类型的特征。

case class TypedResource[T](id: Int) 

object TR { 
    object id { 
    val my_webview = TypedResource[TextView](R.id.my_webview) 
    val my_textview = TypedResource[WebView](R.id.my_textview) 
    //... you must put here all your typed views referenced by id 
    } 
} 

trait TypedViewHolder { 
    def view: View 
    //the method explicitly casts to the needed resource type based on the argument 
    def findView[T](tr: TypedResource[T]): T = view.findViewById(tr.id).asInstanceOf[T] 
} 

object TypedResource { 
    //this will implicitly convert your views to a corresponding TypedViewHolder 
    //this lets you avoid explicit type cast to get your view 
    implicit def view2typed(v: View): TypedViewHolder = new TypedViewHolder { def view = v } 
} 

现在我们可以使用上面的代码

val myView = inflater.inflate(R.layout.my_view, container, false) 
val myWebView = myView.findView(TR.id.my_webview) 
myWebView.loadUrl("http://www.google.com/") 
val myTextView = myView.findView(TR.id.my_textview) 
myTextView.setText("Google.com") 

把这两件事一起

class MyFragment extends Fragment { 
    private var myWebView: Option[WebView] = None 
    private var myTextView: Option[TextView] = None 

    override def onCreateView(
    inflater: LayoutInflater, 
    container: ViewGroup, 
    savedInstanceState: Bundle): View = { 
     //imports the implicit conversion 
     import TypedResource._ 

     val myView = inflater.inflate(R.layout.my_view, container, false) 
     myWebView = Some(myView.findView(TR.id.my_webview)) 
     //now we're using options, so we must call methods on the inner value 
     //we can use Option.map(...) to do it [see http://www.scala-lang.org/api/current/index.html#scala.Option] 
     myWebView.map(_.loadUrl("http://www.google.com/")) 

     myTextView = Some(myView.findView(TR.id.my_textview)) 
     //same as above 
     myTextView.map(_.setText("Google.com")) 
     myView 
    } 
} 

我希望这可以帮助你。我不是android的专家,所以我只能到目前为止。

2

你为什么不干脆写在斯卡拉的片段,而不理会“为此在斯卡拉的最佳方式”?可能没有。

我首先从类定义中删除public,包括文章中的其他好东西 - TypedActivity - 在活动中。然后,设置开发环境 - IDE - 并运行应用程序。如果有效,你就完成了(迁移的第一步)。我认为你从一开始就不需要lazy val

做小的步骤让迁移更容易。

+0

感谢您的回答。第一步已经完成,IDE已经建立,而且它工作正常。我已经删除了私有类成员,并使用“val”作为UI元素。所以,我想进一步尝试改进它。 – Tim 2013-03-04 07:28:26

+0

好!我认为现在是时候在GitHub或类似网站上发布“发现”,并让人们知道源代码是否在那里,这样建议就变得更加集中在你前往的位置。祝你好运! – 2013-03-04 15:59:38

+0

我更新了我的问题,并放入了一些Scala代码。也许你有一些想法,我可以在这里改进? – Tim 2013-03-09 17:43:01

相关问题