2017-05-25 54 views
0

如何避免在我的應用中使用findViewById。佈局非常複雜,findViewById遍歷它的樹來查找需要時間的視圖,並且它被多次使用。替代和快速替換android中的findViewById

+0

「我怎樣才能避免我的應用程序中使用findViewById」 - 這是不是很實用。 「findViewById遍歷它的樹來查找需要時間的視圖」 - 你的證明是,究竟是什麼?請提供一個[mcve],顯示你如何衡量時間和花費多少時間。 – CommonsWare

+0

http://jakewharton.github.io/butterknife/ –

+0

https://code.tutsplus.com/tutorials/quick-tip-using-butter-knife-to-inject-views-on-android--cms-23542 –

回答

2

首先,你必須編輯應用程序的文件的build.gradle,並添加以下到安卓塊:

android { 
 
    … 
 
    dataBinding.enabled = true 
 
}

接下來的事情是使外改變佈局文件標籤,而不是無論你使用的ViewGroup:

<layout xmlns:android="http://schemas.android.com/apk/res/android" 
 
     xmlns:tools="http://schemas.android.com/tools"> 
 
    <RelativeLayout 
 
      android:layout_width="match_parent" 
 
      android:layout_height="match_parent" 
 
      android:paddingLeft="@dimen/activity_horizontal_margin" 
 
      android:paddingRight="@dimen/activity_horizontal_margin" 
 
      android:paddingTop="@dimen/activity_vertical_margin" 
 
      android:paddingBottom="@dimen/activity_vertical_margin" 
 
      tools:context=".MainActivity"> 
 

 
     <TextView 
 
       android:id="@+id/hello" 
 
       android:layout_width="wrap_content" 
 
       android:layout_height="wrap_content"/> 
 

 
    </RelativeLayout> 
 
</layout>

佈局標記告訴Android Studio此佈局應在編譯期間進行額外處理以查找所有有趣的視圖並在下一步中記下它們。沒有外部佈局標籤的所有佈局都不會獲得額外的處理步驟,因此您可以將它們隨意放置到新項目中,而無需更改應用程序其餘部分中的任何內容。 接下來要做的事情就是告訴它在運行時以不同的方式加載佈局文件。因爲這一切都可以回到Eclaire版本,所以不需要依賴新的框架更改來加載這些預處理的佈局文件。因此,你必須對你的加載程序做一些小改動。 而不是從一個活動,:

setContentView(R.layout.hello_world); 
 
TextView hello = (TextView) findViewById(R.id.hello); 
 
hello.setText("Hello World"); // for example, but you'd use 
 
           // resources, right? 
 
You load it like this: 
 

 
HelloWorldBinding binding = 
 
    DataBindingUtil.setContentView(this, R.layout.hello_world); 
 
binding.hello.setText("Hello World"); // you should use resources!

在這裏你可以看到一個類,HelloWorldBinding是爲hello_world.xml佈局文件,並與ID「的觀點@ + ID生成/你好「分配給你可以使用的最後一個字段你好。沒有投射,沒有findViewById。 事實證明,這種訪問視圖的機制不僅比findViewById容易得多,而且也可以更快!綁定過程對佈局中的所有視圖進行單次傳遞,以將視圖分配給字段。當您運行findViewById時,每次都會查看層次結構以查找它。你會看到的一件事是,它會將你的變量名稱化(就像hello_world.xml成爲類HelloWorldBinding),所以如果你給它ID「@ + id/hello_text」,那麼字段名稱就是helloText。 當您爲RecyclerView,ViewPager或其他未設置活動內容的事物充氣時,您需要在生成的類上使用生成的類型安全方法。有幾個版本與LayoutInflater相匹配,所以請使用最適合您使用的版本。例如:

HelloWorldBinding binding = HelloWorldBinding.inflate(
 
    getLayoutInflater(), container, attachToContainer);

如果你沒有安裝充氣查看到含ViewGroup中,你必須可以訪問充氣觀層次。

linearLayout.addView(binding.getRoot());

0

您有幾種選擇,兩個主要有:

Android的數據綁定: https://developer.android.com/topic/libraries/data-binding/index.html

您可以從綁定的getRoot()方法做到這一點

Butterknife: http://jakewharton.github.io/butterknife/

就我個人而言,我是Butterknife的狂熱粉絲,在可能的地方使用它,值得注意的是,這只是讓您的代碼更好看。我發現Android的數據綁定比Butter Knifes複雜得多(儘管這是更多人的觀點)

據我所知,您可以使用視圖綁定或findViewByID。這裏清楚的是他們做同樣的事情。數據/視圖綁定將在編譯時寫入findViewByID。

視圖綁定只是讓您的代碼更易於閱讀。我沒有意識到對android的任何更改,除非您不再需要投射您的findViewByID。

2

另一種選擇是Kotlin的Android擴展。

// Using R.layout.activity_main from the main source set 
import kotlinx.android.synthetic.main.activity_main.* 

class MyActivity : Activity() { 
    override fun onCreate(savedInstanceState: Bundle?) { 
     super.onCreate(savedInstanceState) 
     setContentView(R.layout.activity_main) 

     // Instead of findView(R.id.textView) as TextView 
     textView.setText("Hello, world!") 
    } 
} 

https://kotlinlang.org/docs/tutorials/android-plugin.html

+0

在android studio 3中支持Kotlin? –

+0

@QasimHasnain甚至在此之前它實際上受到支持。 (https://blog.jetbrains.com/kotlin/2013/08/working-with-kotlin-in-android-studio/)。但它捆綁在Android Studio 3.0中。 –