本程式碼研究室是 Android Kotlin 基礎課程的一部分。使用程式碼研究室逐步完成程式碼課程後,您將能充分發揮本課程的潛能。所有課程程式碼研究室清單均列於 Android Kotlin 基礎程式碼研究室到達網頁。
簡介
在上一堂課程中,本課程說明瞭如何從網路服務取得有關火星的房地產資料,以及如何建立具備格線版面配置的 RecyclerView
,以載入及顯示這些資料的圖片。在這個程式碼研究室中,您將根據是否允許租看或購買,以篩選 MarsRealEstate 應用程式來篩選火星屬性。你也可以建立詳細視圖,這樣使用者輕觸總覽中的資源相片時,就會看到詳細屬性的詳細資料。
須知事項
- 如何建立及使用片段。
- 如何在片段之間瀏覽,並使用安全架構 (Gradle 外掛程式) 在片段之間傳送資料。
- 如何使用架構元件,包括檢視模型、查看模型工廠、轉換和
LiveData
。 - 如何從 REST 網路服務擷取 JSON 編碼資料,並使用 Retrofit 和 Moshi 程式庫將該資料剖析為 Kotlin 物件。
您將會瞭解的內容
- 如何在版面配置檔案中使用複雜的繫結運算式。
- 如何透過查詢選項向網路服務發出 Retrofit 要求。
要執行的步驟
- 修改 MarsRealEstate 應用程式,使用「美元符號」圖示標示待售的火星資產 (而非出租的物業)。
- 使用總覽頁面上的選項選單建立網路服務要求,並依類型篩選火星屬性。
- 為 Mars 屬性建立詳細片段,使用導覽功能將片段掛上總覽格線,然後將屬性資料傳送至該片段。
在這個程式碼研究室 (和相關的程式碼研究室中) 中,您可以使用名為 MarsRealEstate 的應用程式,在火星上展示待售房地產。這個應用程式會連線至網際網路伺服器,以擷取和顯示屬性資料,包括價格、是否販售或出租等詳細資料。每個資源代表的圖片都是從 NASA 所拍攝的火星漫遊的實景照片。在先前的程式碼研究室中,您已建立包含所有屬性相片的格狀版面配置的 RecyclerView
:
在這個版本的應用程式中,您需處理資源類型 (出租或購買),並在網格版面配置中加入圖示,以標記待售房地產:
您修改了應用程式的選項選單,以篩選格狀畫面,只顯示出租或銷售的屬性:
最後,您可以為個別資源建立詳細檢視,然後透過總覽,將總覽格線中的圖示連結至該詳細資料片段:
截至目前為止,您使用的 Mars 屬性資料中只有一部分是資源圖片的網址。不過,您在 MarsProperty
類別中定義的資源資料也包含 ID、價格和類型 (出租或銷售)。重新整理記憶中,以下是從網路服務取得的 JSON 資料片段:
{
"price":8000000,
"id":"424908",
"type":"rent",
"img_src": "http://mars.jpl.nasa.gov/msl-raw-images/msss/01000/mcam/1000ML0044631290305226E03_DXXX.jpg"
},
在這項工作中,您會開始與火星的資源類型合作,在要銷售的總覽頁面中的屬性中加入美元符號圖片。
步驟 1:更新 MarsProperty 以納入類型
MarsProperty
類別可定義網路服務提供的各個屬性的資料結構。在先前的程式碼研究室中,您已使用 Moshi 程式庫將 Mars 網路服務的原始 JSON 回應剖析為個別的 MarsProperty
資料物件。
在這個步驟中,您會為 MarsProperty
類別新增一些邏輯,指出特定屬性是否屬於出租物 (亦即該類型是否為 "rent"
或 "buy"
字串)。您會將這個邏輯放在多個位置,所以最好在資料類別中使用這個邏輯,而不是複製資料。
- 從最後一個程式碼研究室開啟 MarsRealEstate 應用程式。(如果您沒有這個應用程式,可以下載 MarsRealEstateGrid)。
- 開啟
network/MarsProperty.kt
。在MarsProperty
類別定義中新增主體,並為isRental
新增自訂 getter,若物件類型為"rent"
,則傳回true
。
data class MarsProperty(
val id: String,
@Json(name = "img_src") val imgSrcUrl: String,
val type: String,
val price: Double) {
val isRental
get() = type == "rent"
}
步驟 2:更新格狀項目版面配置
現在,您可以更新圖片方格的商品項目版面配置,只針對要銷售的屬性圖片顯示美元符號。
您可以使用資料繫結運算式,在網格項目的 XML 版面配置中完全測試。
- 開啟
res/layout/grid_view_item.xml
。這是RecyclerView
格線內每個儲存格的版面配置檔案。這個檔案目前只包含屬性圖片的<ImageView>
元素。 - 在
<data>
元素中,為View
類別新增<import>
元素。當您要在版面配置檔案的資料繫結運算式中使用類別的元件時,就可以使用匯入功能。在這個範例中,您應要使用View.GONE
和View.VISIBLE
常數,所以您需要存取View
類別。
<import type="android.view.View"/>
FrameLayout
<FrameLayout
android:layout_width="match_parent"
android:layout_height="170dp">
<ImageView
android:id="@+id/mars_image"
...
</FrameLayout>
- 針對
ImageView
,請將android:layout_height
屬性變更為match_parent
,以填入新的父項FrameLayout
。
android:layout_height="match_parent"
- 在
FrameLayout
底下的第一個元素下方新增第二個<ImageView>
元素。請使用下方定義的定義。這張圖片顯示在格線項目右下角 (位於火星圖片的上方),並使用「res/drawable/ic_for_sale_outline.xml
」所定義的可繪項目做為貨幣符號圖示。
<ImageView
android:id="@+id/mars_property_type"
android:layout_width="wrap_content"
android:layout_height="45dp"
android:layout_gravity="bottom|end"
android:adjustViewBounds="true"
android:padding="5dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_for_sale_outline"
tools:src="@drawable/ic_for_sale_outline"/>
- 將
android:visibility
屬性新增至mars_property_type
圖片檢視。使用繫結運算式來測試資源類型,並將顯示設定指定為View.GONE
(出租) 或View.VISIBLE
(購買)。
android:visibility="@{property.rental ? View.GONE : View.VISIBLE}"
目前,你只看到版面配置中使用 <data>
元素中定義的個別變數。繫結運算式具有強大功能,可讓你直接在 XML 版面配置中執行測試和數學計算等作業。在這個案例中,您需要使用三元運算子 (?:
) 來執行測試 (此物件是租車嗎?)。您只為一項結果提供真實結果 (用 View.GONE
隱藏錢幣符號圖示),另一個結果為 false (以 View.VISIBLE
顯示該圖示)。
完整的 grid_view_item.xml
檔案如下所示:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View"/>
<variable
name="property"
type="com.example.android.marsrealestate.network.MarsProperty" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="170dp">
<ImageView
android:id="@+id/mars_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
android:padding="2dp"
app:imageUrl="@{property.imgSrcUrl}"
tools:src="@tools:sample/backgrounds/scenic"/>
<ImageView
android:id="@+id/mars_property_type"
android:layout_width="wrap_content"
android:layout_height="45dp"
android:layout_gravity="bottom|end"
android:adjustViewBounds="true"
android:padding="5dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_for_sale_outline"
android:visibility="@{property.rental ? View.GONE : View.VISIBLE}"
tools:src="@drawable/ic_for_sale_outline"/>
</FrameLayout>
</layout>
- 編譯並執行應用程式。請注意,非租賃的屬性具有美元符號圖示。
您的應用程式目前會在總覽格線中顯示「所有」火星屬性。假設有使用者在火星上買有房租的房源,請用圖示來表示有哪些房源適合出售,但網頁上還是有許多資源可供捲動瀏覽。在這項工作中,您必須在總覽片段中加入選項選單,讓使用者只顯示出租物、僅限銷售的物業或全部顯示。
要完成這項工作,其中一種方法就是在總覽格狀空間中測試每個 MarsProperty
的類型,然後只顯示相符的屬性。不過,實際的火星網路服務具有查詢參數或選項 (稱為 filter
),可讓您取得 rent
類型或 buy
類型的屬性。您可以按照下列瀏覽器,在 realestate
網路服務網址中使用這個篩選器查詢:
https://android-kotlin-fun-mars-server.appspot.com/realestate?filter=buy
在這項工作中,您可以修改 MarsApiService
類別,將查詢選項新增至含有 Retrofit 的網路服務要求。然後,透過選項選單,使用該查詢選項重新下載所有火星屬性資料。您從網路服務收到的回應僅包含您感興趣的屬性,因此無需變更總覽格線的檢視顯示邏輯。
步驟 1:更新 Mars API 服務
如要變更要求,您必須重新瀏覽您在本系列中第一個程式碼研究室實作的 MarsApiService
類別。您必須修改類別來提供篩選 API。
- 開啟
network/MarsApiService.kt
。在匯入的正下方,建立一個名為MarsApiFilter
的enum
,以定義與網路服務預期的查詢值相符的常數。
enum class MarsApiFilter(val value: String) {
SHOW_RENT("rent"),
SHOW_BUY("buy"),
SHOW_ALL("all") }
- 修改
getProperties()
方法以取得篩選器查詢的字串輸入內容,並使用@Query("filter")
對其輸入註解 (如下所示)。
在系統提示時匯入retrofit2.http.Query
。@Query
註解會通知getProperties()
方法 (進而改寫),以透過篩選器選項提出網路服務要求。每次呼叫getProperties()
時,要求網址都會包含?filter=type
部分,這可引導網路服務傳回符合該查詢的結果。
fun getProperties(@Query("filter") type: String):
步驟 2:更新總覽檢視模式
您在 OverviewViewModel
的 getMarsRealEstateProperties()
方法中要求 MarsApiService
的資料。現在,您必須更新該要求,才能使用篩選器引數。
- 開啟
overview/OverviewViewModel.kt
。由於您在上一個步驟中所做的變更,將會在 Android Studio 中看到錯誤。將MarsApiFilter
(可能的篩選器值的列舉) 新增為getMarsRealEstateProperties()
呼叫的參數。
收到要求時匯入com.example.android.marsrealestate.network.MarsApiFilter
。
private fun getMarsRealEstateProperties(filter: MarsApiFilter) {
- 修改 Retrofit 服務中對
getProperties()
的呼叫,以字串的形式傳送篩選查詢。
var getPropertiesDeferred = MarsApi.retrofitService.getProperties(filter.value)
- 在
init {}
區塊中,將MarsApiFilter.SHOW_ALL
做為引數傳遞至getMarsRealEstateProperties()
,以便在應用程式初次載入時顯示所有屬性。
init {
getMarsRealEstateProperties(MarsApiFilter.SHOW_ALL)
}
- 在類別的結尾新增
updateFilter()
方法,該方法接受MarsApiFilter
引數,並以該引數呼叫getMarsRealEstateProperties()
。
fun updateFilter(filter: MarsApiFilter) {
getMarsRealEstateProperties(filter)
}
步驟 3:將片段連結至選項選單
最後一步是將溢位選單連接至片段,以便在使用者選取選單選項時,呼叫檢視模型上的 updateFilter()
。
- 開啟
res/menu/overflow_menu.xml
。MarsRealEstate 應用程式有現成的溢位選單,當中提供三種可用的選項:顯示所有屬性、只顯示出租物件,以及僅顯示待售房地產。
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/show_all_menu"
android:title="@string/show_all" />
<item
android:id="@+id/show_rent_menu"
android:title="@string/show_rent" />
<item
android:id="@+id/show_buy_menu"
android:title="@string/show_buy" />
</menu>
- 開啟
overview/OverviewFragment.kt
。在類別的結尾,執行onOptionsItemSelected()
方法來處理選單項目選項。
override fun onOptionsItemSelected(item: MenuItem): Boolean {
}
- 在
onOptionsItemSelected()
中,使用適當的篩選器在檢視模型上呼叫updateFilter()
方法。使用 Kotlinwhen {}
區塊來切換選項。使用MarsApiFilter.SHOW_ALL
做為預設的篩選器值。由於您處理了菜單品項,因此傳回true
。在要求時匯入MarsApiFilter
(com.example.android.marsrealestate.network.MarsApiFilter
)。以下顯示完整的onOptionsItemSelected()
方法。
override fun onOptionsItemSelected(item: MenuItem): Boolean {
viewModel.updateFilter(
when (item.itemId) {
R.id.show_rent_menu -> MarsApiFilter.SHOW_RENT
R.id.show_buy_menu -> MarsApiFilter.SHOW_BUY
else -> MarsApiFilter.SHOW_ALL
}
)
return true
}
- 編譯並執行應用程式。應用程式會啟動第一個總覽格線,其中包含所有屬性類型,以及有 1 個代表貨幣圖示的待售屬性。
- 從選項選單中選擇 [租看]。屬性會重新載入,但當中不會出現任何貨幣圖示。(只顯示出租資源)。您可能需要稍候片刻,讓螢幕重新整理,只顯示經過篩選的屬性。
- 從選項選單中選擇 [購買]。屬性會重新載入,而所有資源都會顯示為美元圖示。(只顯示待售資源)。
現在,您擁有火星屬性的圖示捲動捲軸,但現在該詳細說明瞭。在這項工作中,您會加入一個詳細片段,以顯示特定屬性的詳細資料。詳細資料片段會顯示較大的圖片、價格和資源類型,無論是出租或出售。
當使用者輕觸總覽格線中的圖片時,即會啟動這個片段。如要達成這個目的,您必須將 onClick
監聽器新增至 RecyclerView
格線項目,然後瀏覽到新片段。瀏覽「ViewModel
」時,您必須觸發 LiveData
變更 (相關課程內容均已完成)。您也可以使用導覽元件外掛程式,將所選 MarsProperty
資訊從總覽片段傳送至詳細片段。
步驟 1:建立詳細資料視圖模型並更新詳細資料版面配置
就如同您對總覽檢視模型和片段的程序一樣,現在您也需要為詳細片段實作檢視模型和版面配置檔案。
- 開啟
detail/DetailViewModel.kt
。與網路相關的 Kotlin 檔案一樣位於network
資料夾和overview
的總覽檔案中,detail
資料夾則包含與詳細資料檢視相關的檔案。請注意,DetailViewModel
類別 (目前為空白) 會使用marsProperty
做為建構函式中的參數。
class DetailViewModel( marsProperty: MarsProperty,
app: Application) : AndroidViewModel(app) {
}
- 在類別定義中,為所選的 Mars 屬性新增
LiveData
,讓詳細資訊顯示在詳細檢視畫面中。請按照一般模式建立MutableLiveData
以保存MarsProperty
本身,然後公開不可變更的公開LiveData
屬性。
在需要時匯入androidx.lifecycle.LiveData
並匯入androidx.lifecycle.MutableLiveData
。
private val _selectedProperty = MutableLiveData<MarsProperty>()
val selectedProperty: LiveData<MarsProperty>
get() = _selectedProperty
- 建立一個
init {}
區塊,並使用建構函式中的MarsProperty
物件設定選定的 Mars 屬性值。
init {
_selectedProperty.value = marsProperty
}
- 開啟「
res/layout/fragment_detail.xml
」並在設計檢視模式中查看。
此為詳細片段的版面配置檔案。內含大型相片的ImageView
、物業類型 (出租或銷售) 的TextView
和價格的TextView
。請注意,限製版面配置會以ScrollView
包覆,因此如果畫面過大 (例如使用者在橫向模式中觀看影片),就會自動捲動。 - 前往版面配置的「文字」分頁。在版面配置頂端,就在
<ScrollView>
元素之前,新增<data>
元素,將詳細資料檢視模型與版面配置建立關聯。
<data>
<variable
name="viewModel"
type="com.example.android.marsrealestate.detail.DetailViewModel" />
</data>
- 將
app:imageUrl
屬性新增至ImageView
元素。在檢視模式中選取此屬性即可設為imgSrcUrl
。
透過 Glide 載入圖片的繫結轉接程式也會自動在這裡使用,因為該轉接程式會監控所有app:imageUrl
屬性。
app:imageUrl="@{viewModel.selectedProperty.imgSrcUrl}"
步驟 2:在總覽檢視模式中定義導覽
當使用者在總覽模型中輕觸相片時,系統應在片段中啟動瀏覽點擊項目的相關詳細資料。
- 開啟
overview/OverviewViewModel.kt
。新增_navigateToSelectedProperty
MutableLiveData
屬性並透過不可變更的LiveData
將其公開。
當此LiveData
變更為非空值時,即會觸發導覽。(不久之後,您就會加入程式碼來觀察這個變數並觸發導覽)。
private val _navigateToSelectedProperty = MutableLiveData<MarsProperty>()
val navigateToSelectedProperty: LiveData<MarsProperty>
get() = _navigateToSelectedProperty
- 在類別的結尾,新增
displayPropertyDetails()
方法來將 _navigateToSelectedProperty
加入所選的 Mars 屬性。
fun displayPropertyDetails(marsProperty: MarsProperty) {
_navigateToSelectedProperty.value = marsProperty
}
- 加入空值
_navigateToSelectedProperty
的displayPropertyDetailsComplete()
方法。您需要執行這項操作,才能將導航狀態標示為已完成,並避免使用者在詳細資料檢視中再次觸發導覽。
fun displayPropertyDetailsComplete() {
_navigateToSelectedProperty.value = null
}
步驟 3:在格線轉接程式和片段中設定點擊事件監聽器
- 開啟
overview/PhotoGridAdapter.kt
。在類別的結尾建立自訂OnClickListener
類別,並擷取包含marsProperty
參數的 lambda。在類別內,定義設為 lambda 參數的onClick()
函式。
class OnClickListener(val clickListener: (marsProperty:MarsProperty) -> Unit) {
fun onClick(marsProperty:MarsProperty) = clickListener(marsProperty)
}
- 捲動至「
PhotoGridAdapter
」的類別定義,並在建構函式中新增私人OnClickListener
屬性。
class PhotoGridAdapter( private val onClickListener: OnClickListener ) :
ListAdapter<MarsProperty,
PhotoGridAdapter.MarsPropertyViewHolder>(DiffCallback) {
- 在
onBindviewHolder()
方法的網格項目中加入onClickListener
,即可將相片設為可點擊。定義在呼叫getItem() and bind()
之間的點擊事件監聽器。
override fun onBindViewHolder(holder: MarsPropertyViewHolder, position: Int) {
val marsProperty = getItem(position)
holder.itemView.setOnClickListener {
onClickListener.onClick(marsProperty)
}
holder.bind(marsProperty)
}
- 開啟
overview/OverviewFragment.kt
。在onCreateView()
方法中,將初始化binding.photosGrid.adapter
屬性的那一行替換為下列幾行。
這段程式碼會將PhotoGridAdapter.onClickListener
物件新增至PhotoGridAdapter
建構函式,並呼叫viewModel.displayPropertyDetails()
和傳遞的MarsProperty
物件。這會在導航的檢視模式中觸發LiveData
。
binding.photosGrid.adapter = PhotoGridAdapter(PhotoGridAdapter.OnClickListener {
viewModel.displayPropertyDetails(it)
})
步驟 4:修改導覽圖表,並調整 MarsProperty 的屬性
當使用者在總覽格線中輕觸相片時,應用程式應該瀏覽至詳細資料片段,並且傳遞所選 Mars 屬性的詳細資料,讓詳細資料檢視畫面能顯示相關資訊。
現在,「PhotoGridAdapter
」有一個點擊事件監聽器可用來處理輕觸操作,以及從檢視模型觸發導覽的方法。但您尚未將 MarsProperty
物件傳遞至詳細資料片段。請在導覽元件中使用安全架構。
- 開啟
res/navigation/nav_graph.xml
。按一下 [文字] 標籤即可查看導覽圖表的 XML 程式碼。 - 在詳細資料片段的
<fragment>
元素中,新增下方顯示的<argument>
元素。此引數稱為selectedProperty
,其類型為MarsProperty
。
<argument
android:name="selectedProperty"
app:argType="com.example.android.marsrealestate.network.MarsProperty"
/>
- 編譯應用程式。由於
MarsProperty
沒有可剖析的錯誤,因此導覽將會顯示錯誤訊息。Parcelable
介面可讓物件序列化,以便讓物件在片段或活動之間來回傳送。在這個情況下,要通過安全聲明MarsProperty
對象內的數據,MarsProperty
必須執行Parcelable
界面。好消息是 Kotlin 提供了一個簡單的捷徑來實作該介面。 - 開啟
network/MarsProperty.kt
。在類別定義中加入@Parcelize
註解。
要求時匯入kotlinx.android.parcel.Parcelize
。@Parcelize
註解會使用 Kotlin Android 擴充功能,針對這個類別自動在Parcelable
介面中實作方法。您無須採取其他動作!
@Parcelize
data class MarsProperty (
- 變更
MarsProperty
的類別定義以延長Parcelable
。
按要求匯入android.os.Parcelable
。MarsProperty
類別定義現在如下所示:
@Parcelize
data class MarsProperty (
val id: String,
@Json(name = "img_src") val imgSrcUrl: String,
val type: String,
val price: Double) : Parcelable {
步驟 5:連接片段
您仍在瀏覽,因為實際的瀏覽作業會位於片段中。在這個步驟中,您會新增最後一個位元來實作總覽和詳細片段之間的導覽。
- 開啟
overview/OverviewFragment.kt
。在onCreateView()
中,在初始化相片格狀轉接程式的線條下方,加入下列幾行即可從總覽檢視模型觀察navigatedToSelectedProperty
。
在需要時匯入androidx.lifecycle.Observer
並匯入androidx.navigation.fragment.findNavController
。
觀測器會測試MarsProperty
(在 lambda 中的it
) 是否為空值;如果是的話,則會透過findNavController()
從片段取得導覽控制器。呼叫displayPropertyDetailsComplete()
要求檢視模型將LiveData
重設為空值,因此當應用程式返回OverviewFragment
時,不會意外觸發導航程序。
viewModel.navigateToSelectedProperty.observe(this, Observer {
if ( null != it ) {
this.findNavController().navigate(
OverviewFragmentDirections.actionShowDetail(it))
viewModel.displayPropertyDetailsComplete()
}
})
- 開啟
detail/DetailFragment.kt
。在onCreateView()
方法的呼叫setLifecycleOwner()
下方新增這一行。這一行程式碼會從「Safe Args」中取得所選的MarsProperty
物件。
請注意,使用 Kotlin 時不是使用 null 的斷言運算子 (!!
)。如果selectedProperty
不存在,代表發生了問題,您實際卻希望程式碼可以傳回一個空值。(在實際工作環境程式碼中,您應以某種方式處理這個錯誤)。
val marsProperty = DetailFragmentArgs.fromBundle(arguments!!).selectedProperty
- 新增這一行即可取得新的
DetailViewModelFactory
。您將使用DetailViewModelFactory
取得DetailViewModel
的執行個體。啟動應用程式包含DetailViewModelFactory
的實作,因此您只需要在這裡初始化應用程式。
val viewModelFactory = DetailViewModelFactory(marsProperty, application)
- 最後,加入這一行即可從工廠取得
DetailViewModel
,並且連接所有零件。
binding.viewModel = ViewModelProviders.of(
this, viewModelFactory).get(DetailViewModel::class.java)
- 編譯並執行應用程式,然後輕觸任何火星屬性相片。這樣即可看到該資源的詳細資料詳情片段。輕觸 [返回] 按鈕即可返回總覽頁面,並注意到詳細資訊畫面仍是稀疏畫面。您會在下一個工作中,將屬性資料新增至該詳細資料頁面。
現在,詳細資料頁面只會顯示與總覽頁面上相同的火星相片。「MarsProperty
」類別也有資源類型 (出租或購買) 和房源價格。詳細資料畫面應包含這兩個值;如果出租屬性指出價格是每月價格,則這項資訊十分有用。您可以在檢視模型中使用 LiveData
轉換來同時執行這兩項操作。
- 開啟
res/values/strings.xml
。範例程式碼包含字串資源 (如下所示),可協助您建立詳細資料檢視畫面的字串。根據價格類型,您必須使用display_price_monthly_rental
資源或display_price
資源 (視資源類型而定)。
<string name="type_rent">Rent</string>
<string name="type_sale">Sale</string>
<string name="display_type">For %s</string>
<string name="display_price_monthly_rental">$%,.0f/month</string>
<string name="display_price">$%,.0f</string>
- 開啟
detail/DetailViewModel.kt
。在課程底部加入下方顯示的代碼。
如果系統要求,請匯入androidx.lifecycle.Transformations
。
此轉換會使用第一項工作使用的相同測試來測試所選資源是否為租屋。如果屬性是租金,則轉換作業會從含有 Kotlinwhen {}
開關的資源中選擇適當的字串。這兩個字串的結尾都需要有數字,因此之後可以將property.price
串連起來。
val displayPropertyPrice = Transformations.map(selectedProperty) {
app.applicationContext.getString(
when (it.isRental) {
true -> R.string.display_price_monthly_rental
false -> R.string.display_price
}, it.price)
}
- 匯入產生的
R
類別,以便存取專案中的字串資源。
import com.example.android.marsrealestate.R
displayPropertyPrice
轉換之後,請加入下方所示的程式碼。這個轉換會根據多個屬性類型 (出租) 來串聯多個字串資源。
val displayPropertyType = Transformations.map(selectedProperty) {
app.applicationContext.getString(R.string.display_type,
app.applicationContext.getString(
when (it.isRental) {
true -> R.string.type_rent
false -> R.string.type_sale
}))
}
- 開啟
res/layout/fragment_detail.xml
。還有一件事要做的,就是將新字串 (您使用LiveData
轉換建立) 繫結至詳細資料檢視畫面。做法是將資源類型文字的文字欄位值設為viewModel.displayPropertyType
,並將價格文字文字欄位的文字欄位設為viewModel.displayPropertyPrice
。
<TextView
android:id="@+id/property_type_text"
...
android:text="@{viewModel.displayPropertyType}"
...
tools:text="To Rent" />
<TextView
android:id="@+id/price_value_text"
...
android:text="@{viewModel.displayPropertyPrice}"
...
tools:text="$100,000" />
- 請編譯並執行應用程式。現在所有屬性資料都顯示在詳細資訊頁面上,格式正確。
Android Studio 專案:MarsRealEstateFinal
繫結運算式
- 您可以在 XML 版面配置檔案中使用繫結運算式,對已繫結的資料執行簡單的程式輔助作業,例如數學或條件測試。
- 如要參照版面配置檔案中的類別,請使用
<data>
標記內的<import>
標記。
網路服務查詢選項
- 對網路服務的要求可以包含選用參數。
- 如要在要求中指定查詢參數,請使用 Retrofit 中的
@Query
註解。
Udacity 課程:
Android 開發人員說明文件:
- ViewModel 總覽
- LiveData 總覽
- 繫結轉接器
- 版面配置與繫結運算式
- 導覽
- 開始使用導覽元件
- 在目的地之間傳送資料 (另請參閱「安全拱門」)
Transformations
類別ViewModelProvider
類別ViewModelProvider.Factory
類別
其他:
- 滑行
- Retrofit Query 類別
- Kotlin's PPcelable generator 擴充功能
這個部分會列出在代碼研究室中,受老師主導的課程作業的可能學生作業。由老師自行決定要執行下列動作:
- 視需要指派家庭作業。
- 告知學生如何提交家庭作業。
- 批改家庭作業。
老師可視需要使用這些建議,並視情況指派其他合適的家庭作業。
如果您是自行操作本程式碼研究室,歡迎透過這些家庭作業來測試自己的知識。
回答這些問題
第 1 題
XML 版面配置檔案中的 <import>
標記有什麼作用?
▢ 在不同版面配置中納入一個版面配置檔案。
▢ 將 Kotlin 程式碼嵌入版面配置檔案。
▢ 提供資料繫結屬性的存取權。
▢ 可在繫結運算式中參照類別和類別成員。
第 2 題
如何將查詢選項新增至 Retrofit 中的 REST 網路服務呼叫?
▢ 將查詢附加到要求網址的結尾。
▢ 將查詢的參數新增至發出要求的函式,並以 @Query
為該參數加上註解。
▢ 使用 Query
類別建立要求。
▢ 使用 Retrofit 建構工具中的 addQuery()
方法。
開始下一門課程:
如要瞭解本課程中其他程式碼研究室的連結,請參閱 Android Kotlin 基礎程式碼程式碼到達網頁。