2013-03-03 23 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

相關問題