這個程式碼研究室是 Android Kotlin 基礎知識課程的一部分。如果您按部就班完成程式碼研究室,就能充分體驗到本課程的價值。所有課程程式碼研究室都列在 Android Kotlin 基礎知識程式碼研究室到達網頁。
簡介
在先前的程式碼研究室中,您已瞭解如何從網路服務獲取資料,並將回應剖析為資料物件。在本程式碼研究室中,您可以在該知識的基礎上,瞭解如何從網址載入並顯示相片。您也可以回顧如何建構 RecyclerView,並在總覽頁面用以顯示圖片格線。
須知事項
- 如何建立及使用片段。
- 如何使用架構元件,包括檢視畫面模型、檢視畫面模型工廠、轉換和
LiveData。 - 如何從 REST 網路服務擷取 JSON,並使用 Retrofit 和 Moshi 程式庫將資料剖析為 Kotlin 物件。
- 如何使用
RecyclerView建構格線版面配置。 Adapter、ViewHolder和DiffUtil的運作方式。
課程內容
- 如何使用 Glide 程式庫從網址載入及顯示圖片。
- 如何使用
RecyclerView和格線轉接器顯示圖片格線。 - 如何處理圖片下載及顯示時出現的潛在錯誤。
執行步驟
- 修改 MarsRealEstate 應用程式,從火星房地產資料取得圖片網址,並使用 Glide 載入及顯示該圖片。
- 在應用程式中新增載入動畫和錯誤圖示。
- 使用
RecyclerView顯示火星房地產圖片格線。 - 為
RecyclerView加入狀態和錯誤處理機制。
在本程式碼研究室 (和相關程式碼研究室) 中,您將使用名為 MarsRealEstate 的應用程式,顯示火星上的待售地產。應用程式會連線至網際網路伺服器,擷取並顯示房地產資料,包括價格和房地產是否待售或待租等詳細資料。代表各個屬性的圖片是自 NASA 火星漫遊者擷取的火星實景相片。

您在本程式碼研究室中建構的應用程式版本會填入總覽頁面,此頁面會顯示圖片格線。這些圖片來自您的應用程式從 Mars 房地產網路服務取得的房地產資料。您的應用程式會使用 Glide 程式庫來載入並顯示圖片,也會使用 RecyclerView 來建立圖片的格線版面配置。此外,應用程式還會妥善處理網路錯誤。
想要顯示某個網址的相片,聽起來可能很簡單,但其實需要執行一些軟體工程才能達成。圖片必須經過下載、緩衝處理、對壓縮格式進行解碼,才能供 Android 使用。圖片應快取至記憶體快取或儲存空間快取,或同時存放在這兩個地方。系統只會在低優先順序的背景執行緒中採取這些動作,讓 UI 保持回應。此外,為獲得最佳網路和 CPU 效能,建議您一次擷取多張圖片並解碼。如何有效載入網路圖片本身就是一個程式碼研究室。
好消息是,您可以使用社群開發的程式庫 Glide 下載、緩衝處理、解碼及快取圖片。與從頭開始執行所有作業相比,Glide 可大幅減少您的工作量。
Glide 基本上需要下列兩項:
- 要載入並顯示的圖片網址。
- 用來顯示該圖片的
ImageView物件。
在這項工作中,您會瞭解如何使用 Glide 顯示來自房地產 Web 服務的單張圖片。Web 服務會傳回地產清單,您將顯示清單上的第一個火星地產圖片。以下是前後對照的螢幕截圖:


步驟 1:新增 Glide 依附元件
- 開啟上一個程式碼研究室中的 MarsRealEstate 應用程式。(如果沒有這個應用程式,可以MarsRealEstateNetwork下載)。
- 執行應用程式以查看其用途。(系統會顯示假設在火星上可用的房地產文字詳細資料)。
- 開啟「build.gradle (Module: app)」。
- 在
dependencies區段,為 Glide 程式庫新增此行內容:
implementation "com.github.bumptech.glide:glide:$version_glide"
請注意,版本號碼已在專案 Gradle 檔案中另外定義。
- 按一下「Sync Now」,使用新依附元件重新建構專案。
步驟 2:更新檢視畫面模型
接著,您會更新 OverviewViewModel 類別,加入單一火星屬性的即時資料。
- 開啟
overview/OverviewViewModel.kt。在_response的LiveData下方,為單一MarsProperty物件新增內部 (可變動) 和外部 (不可變動) 的即時資料。
視需要匯入MarsProperty類別 (com.example.android.marsrealestate.network.MarsProperty)。
private val _property = MutableLiveData<MarsProperty>()
val property: LiveData<MarsProperty>
get() = _property- 在
getMarsRealEstateProperties()方法的try/catch {}區塊中,找出將_response.value設為屬性數量的行。新增下列測試。如果MarsProperty物件可用,這項測試會將_propertyLiveData的值設為listResult中的第一個屬性。
if (listResult.size > 0) {
_property.value = listResult[0]
}現在,完整的 try/catch {} 區塊如下所示:
try {
var listResult = getPropertiesDeferred.await()
_response.value = "Success: ${listResult.size} Mars properties retrieved"
if (listResult.size > 0) {
_property.value = listResult[0]
}
} catch (e: Exception) {
_response.value = "Failure: ${e.message}"
}- 開啟
res/layout/fragment_overview.xml檔案。在<TextView>元素中,將android:text變更為繫結至propertyLiveData的imgSrcUrl元件:
android:text="@{viewModel.property.imgSrcUrl}"- 執行應用程式。
TextView只會顯示第一個火星屬性中的圖片網址。目前,您已設定好該網址的檢視畫面模型和即時資料。

步驟 3:建立繫結介面卡並呼叫 Glide
現在您已取得要顯示的圖片網址,接下來請開始使用 Glide 載入該圖片。在這個步驟中,您會使用繫結轉接器,從與 ImageView 相關聯的 XML 屬性取得網址,並使用 Glide 載入圖片。繫結轉接器是介於檢視畫面和繫結資料之間的擴充方法,可在資料變更時提供自訂行為。在本例中,自訂行為是呼叫 Glide,將網址中的圖片載入 ImageView。
- 開啟
BindingAdapters.kt。這個檔案會保留您在應用程式中使用的繫結轉接器。 - 建立可接受
ImageView和String做為參數的bindImage()函式。使用@BindingAdapter為函式加上註解。@BindingAdapter註解會通知資料繫結,在 XML 項目擁有imageUrl屬性時執行此繫結轉接器。
視需要匯入androidx.databinding.BindingAdapter和android.widget.ImageView。
@BindingAdapter("imageUrl")
fun bindImage(imgView: ImageView, imgUrl: String?) {
}- 在
bindImage()函式中,為imgUrl引數新增let {}區塊:
imgUrl?.let {
}- 在
let {}區塊內,新增下方顯示的程式碼行,將網址字串 (來自 XML) 轉換為Uri物件。視需要匯入androidx.core.net.toUri。
您希望最終的Uri物件使用 HTTPS 通訊協定,因為您從中提取圖片的伺服器需要該通訊協定。如要使用 HTTPS 配置,請將buildUpon.scheme("https")附加至toUri建構工具。toUri()方法是 Android KTX 核心程式庫的 Kotlin 擴充功能函式,因此看起來就像是String類別的一部分。
val imgUri = imgUrl.toUri().buildUpon().scheme("https").build()- 同樣在
let {}中,呼叫Glide.with(),將Uri物件的圖片載入ImageView。依要求匯入com.bumptech.glide.Glide。
Glide.with(imgView.context)
.load(imgUri)
.into(imgView)步驟 4:更新版面配置和片段
雖然 Glide 已載入圖片,但目前沒有任何內容可供查看。下一步是更新版面配置和片段,並使用 ImageView 顯示圖片。
- 開啟
res/layout/gridview_item.xml。這是您稍後在程式碼研究室中,將用於RecyclerView中每個項目的版面配置資源檔案。您在這裡暫時使用它,只顯示單一圖片。 - 在
<ImageView>元素上方,為資料繫結新增<data>元素,並繫結至OverviewViewModel類別:
<data>
<variable
name="viewModel"
type="com.example.android.marsrealestate.overview.OverviewViewModel" />
</data>- 在
ImageView元素中新增app:imageUrl屬性,即可使用新的圖片載入繫結轉接器:
app:imageUrl="@{viewModel.property.imgSrcUrl}"- 開啟
overview/OverviewFragment.kt。在onCreateView()方法中,對於加載FragmentOverviewBinding類別並將其指派給繫結變數的行,排除其註解。請放心,這是暫時現象,稍後就會恢復。
//val binding = FragmentOverviewBinding.inflate(inflater)- 請改為新增一行內容,以加載
GridViewItemBinding類別。依要求匯入com.example.android.marsrealestate. databinding.GridViewItemBinding。
val binding = GridViewItemBinding.inflate(inflater)- 執行應用程式。現在螢幕上會顯示結果清單中第一個
MarsProperty的圖片。
步驟 5:新增簡單的載入和錯誤圖片
Glide 不僅可以顯示預留位置圖片,還能載入圖片,如果因圖片缺失或損毀等原因造成載入失敗,也可以載入錯誤圖片,進而改善使用者體驗。在這個步驟中,您需要為繫結轉接器和版面配置新增該功能。
- 開啟
res/drawable/ic_broken_image.xml,然後按一下右側的「預覽」分頁標籤。如果出現錯誤圖片,表示您使用的是內建圖示庫中的無效圖片圖示。此向量可繪項目使用android:tint屬性,將圖示變為灰色。

- 開啟
res/drawable/loading_animation.xml。這個可繪項目是使用<animate-rotate>標記定義的動畫。動畫會圍繞中心點旋轉圖片可繪項目loading_img.xml。(預覽畫面不會顯示動畫)。

- 返回
BindingAdapters.kt檔案。在bindImage()方法中,更新Glide.with()的呼叫,以便在load()和into()之間呼叫apply()函式。在系統要求時匯入com.bumptech.glide.request.RequestOptions。
此程式碼會設定載入時要使用的預留位置載入圖片 (loading_animation可繪項目),此程式碼也會設定圖片載入失敗時要使用的圖片 (broken_image可繪項目)。現在,完整的bindImage()方法大致如下:
@BindingAdapter("imageUrl")
fun bindImage(imgView: ImageView, imgUrl: String?) {
imgUrl?.let {
val imgUri =
imgUrl.toUri().buildUpon().scheme("https").build()
Glide.with(imgView.context)
.load(imgUri)
.apply(RequestOptions()
.placeholder(R.drawable.loading_animation)
.error(R.drawable.ic_broken_image))
.into(imgView)
}
}
- 執行應用程式。系統可能會在 Glide 下載並顯示屬性圖片時,暫時顯示載入圖片,具體情況視網路連線速度而定。但即使您關閉網路,此刻仍不會顯示毀損圖片圖示。此問題會在程式碼研究室的最後一部分修正。
現在,您的應用程式會從網際網路載入房地產資訊。透過使用第一個 MarsProperty 清單項目的資料,您已在檢視畫面模型中建立 LiveData 屬性,並使用該屬性資料中的圖片網址填入 ImageView。但我們的目標是讓應用程式顯示圖片格線,因此您要使用 RecyclerView 搭配 GridLayoutManager。
步驟 1:更新檢視區塊模型
目前檢視模型有一個 _property LiveData,其中包含一個 MarsProperty 物件,也就是網路服務回應清單中的第一個物件。在此步驟中,您必須變更該 LiveData,使其存放 MarsProperty 物件的完整清單。
- 開啟
overview/OverviewViewModel.kt。 - 將私有
_property變數變更為_properties。將類型變更為MarsProperty物件的清單。
private val _properties = MutableLiveData<List<MarsProperty>>()- 將外部
property即時資料替換為properties。在這裡將清單加入LiveData型別:
val properties: LiveData<List<MarsProperty>>
get() = _properties- 向下捲動至
getMarsRealEstateProperties()方法。在try {}區塊中,將您在上一個工作新增的整個測試,替換為以下顯示的行。由於listResult變數會保留MarsProperty物件的清單,因此您可以將其指派給_properties.value,而不必測試是否成功回應。
_properties.value = listResult現在整個 try/catch 區塊如下所示:
try {
var listResult = getPropertiesDeferred.await()
_response.value = "Success: ${listResult.size} Mars properties retrieved"
_properties.value = listResult
} catch (e: Exception) {
_response.value = "Failure: ${e.message}"
}步驟 2:更新版面配置和片段
下一個步驟是變更應用程式的版面配置和片段,改用回收器檢視畫面和格線版面配置,而非單張圖片檢視畫面。
- 開啟
res/layout/gridview_item.xml。將資料繫結從OverviewViewModel變更為MarsProperty,並將變數重新命名為"property"。
<variable
name="property"
type="com.example.android.marsrealestate.network.MarsProperty" />- 在
<ImageView>中,將app:imageUrl屬性變更為參照MarsProperty物件中的圖片網址:
app:imageUrl="@{property.imgSrcUrl}"- 開啟
overview/OverviewFragment.kt。在onCreateview()中,取消註解加載FragmentOverviewBinding的行。刪除加載GridViewBinding的行或排除其註解。這些變更會復原您在上一個工作中做出的臨時變更。
val binding = FragmentOverviewBinding.inflate(inflater)
// val binding = GridViewItemBinding.inflate(inflater)- 開啟
res/layout/fragment_overview.xml。刪除整個<TextView>元素。 - 請改為新增這個
<RecyclerView>元素,該元素會使用GridLayoutManager和單一項目的grid_view_item版面配置:
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/photos_grid"
android:layout_width="0dp"
android:layout_height="0dp"
android:padding="6dp"
android:clipToPadding="false"
app:layoutManager=
"androidx.recyclerview.widget.GridLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:spanCount="2"
tools:itemCount="16"
tools:listitem="@layout/grid_view_item" />步驟 3:新增相片格線轉接器
現在,fragment_overview 版面配置有 RecyclerView,而 grid_view_item 版面配置則有單一 ImageView。在這個步驟中,您會透過 RecyclerView 轉接器將資料繫結至 RecyclerView。
- 開啟
overview/PhotoGridAdapter.kt。 - 使用如下所示的建構函式參數,建立
PhotoGridAdapter類別。PhotoGridAdapter類別會擴充ListAdapter,其建構函式需要清單項目類型、檢視畫面持有者和DiffUtil.ItemCallback實作。
視需要匯入androidx.recyclerview.widget.ListAdapter和com.example.android.marsrealestate.network.MarsProperty類別。在後續步驟中,您將實作此建構函式缺少的其他部分,這些部分會產生錯誤。
class PhotoGridAdapter : ListAdapter<MarsProperty,
PhotoGridAdapter.MarsPropertyViewHolder>(DiffCallback) {
}- 按一下
PhotoGridAdapter類別中的任意位置,然後按下Control+i實作ListAdapter方法,也就是onCreateViewHolder()和onBindViewHolder()。
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PhotoGridAdapter.MarsPropertyViewHolder {
TODO("not implemented")
}
override fun onBindViewHolder(holder: PhotoGridAdapter.MarsPropertyViewHolder, position: Int) {
TODO("not implemented")
}- 在
PhotoGridAdapter類別定義結尾,於您剛新增的方法後,為DiffCallback新增隨附物件定義,如下所示。
依要求匯入androidx.recyclerview.widget.DiffUtil。
DiffCallback物件會將DiffUtil.ItemCallback擴充為要比較的物件類型:MarsProperty。
companion object DiffCallback : DiffUtil.ItemCallback<MarsProperty>() {
}- 按下
Control+i,為這個物件實作比較器方法,也就是areItemsTheSame()和areContentsTheSame()。
override fun areItemsTheSame(oldItem: MarsProperty, newItem: MarsProperty): Boolean {
TODO("not implemented")
}
override fun areContentsTheSame(oldItem: MarsProperty, newItem: MarsProperty): Boolean {
TODO("not implemented") }- 在
areItemsTheSame()方法中,移除 TODO。使用 Kotlin 的參照等式運算子 (===),如果oldItem和newItem的物件參照相同,則會傳回true。
override fun areItemsTheSame(oldItem: MarsProperty,
newItem: MarsProperty): Boolean {
return oldItem === newItem
}- 對於
areContentsTheSame(),請只對oldItem和newItem的 ID 使用標準等號運算子。
override fun areContentsTheSame(oldItem: MarsProperty,
newItem: MarsProperty): Boolean {
return oldItem.id == newItem.id
}- 仍在
PhotoGridAdapter類別中,在隨附物件下方新增MarsPropertyViewHolder的內部類別定義,該定義可擴充RecyclerView.ViewHolder。
系統要求時,請匯入androidx.recyclerview.widget.RecyclerView和com.example.android.marsrealestate.databinding.GridViewItemBinding。
您需要使用GridViewItemBinding變數將MarsProperty繫結至版面配置,因此請將該變數傳送至MarsPropertyViewHolder。由於基本ViewHolder類別需要在其建構函式中設定檢視畫面,因此您要將其傳送至繫結的根檢視畫面。
class MarsPropertyViewHolder(private var binding:
GridViewItemBinding):
RecyclerView.ViewHolder(binding.root) {
}- 在
MarsPropertyViewHolder中建立bind()方法,將MarsProperty物件做為引數,並將binding.property設為該物件。設定屬性後,請呼叫executePendingBindings(),以立即執行更新作業。
fun bind(marsProperty: MarsProperty) {
binding.property = marsProperty
binding.executePendingBindings()
}- 在
onCreateViewHolder()中,移除 TODO 並新增下列一行內容。依要求匯入android.view.LayoutInflater。onCreateViewHolder()方法需要傳回新的MarsPropertyViewHolder,加載GridViewItemBinding並使用父項ViewGroup背景資訊中的LayoutInflater即可建立。
return MarsPropertyViewHolder(GridViewItemBinding.inflate(
LayoutInflater.from(parent.context)))- 在
onBindViewHolder()方法中,移除 TODO 並新增下列幾行內容。您可以在這裡呼叫getItem(),取得與目前RecyclerView位置相關的MarsProperty物件,然後將該屬性傳遞至MarsPropertyViewHolder中的bind()方法。
val marsProperty = getItem(position)
holder.bind(marsProperty)步驟 4:新增繫結轉接器並連結各個部分
最後,使用 BindingAdapter 初始化包含 MarsProperty 物件清單的 PhotoGridAdapter。若使用 BindingAdapter 設定 RecyclerView 資料,資料繫結將自動監控 LiveData 的 MarsProperty 物件清單。當 MarsProperty 清單有所變更時,系統會自動呼叫繫結轉接器。
- 開啟
BindingAdapters.kt。 - 在檔案結尾,新增
bindRecyclerView()方法,以RecyclerView和MarsProperty物件清單做為引數。請使用@BindingAdapter為該方法加上註解。
視需要匯入androidx.recyclerview.widget.RecyclerView和com.example.android.marsrealestate.network.MarsProperty。
@BindingAdapter("listData")
fun bindRecyclerView(recyclerView: RecyclerView,
data: List<MarsProperty>?) {
}- 在
bindRecyclerView()函式中,將recyclerView.adapter投放至PhotoGridAdapter,然後使用資料呼叫adapter.submitList()。出現新的清單時,這個屬性會通知RecyclerView。
依要求匯入 com.example.android.marsrealestate.overview.PhotoGridAdapter。
val adapter = recyclerView.adapter as PhotoGridAdapter
adapter.submitList(data)- 開啟
res/layout/fragment_overview.xml。接著將app:listData屬性新增至RecyclerView元素,然後使用資料繫結將屬性設為viewmodel.properties。
app:listData="@{viewModel.properties}"- 開啟
overview/OverviewFragment.kt。在onCreateView()中,於呼叫setHasOptionsMenu()之前,將binding.photosGrid中的RecyclerView轉接器初始化為新的PhotoGridAdapter物件。
binding.photosGrid.adapter = PhotoGridAdapter()- 執行應用程式。畫面上應該會顯示
MarsProperty圖片格線。捲動畫面即可查看新圖片,但應用程式會在正常顯示圖片前,先顯示載入進度圖示。開啟飛航模式後,尚未載入的圖片會顯示為無效圖片圖示。

MarsRealEstate 應用程式會將無法擷取的圖片顯示為無效圖片圖示。但是如果沒有網路連線,應用程式會顯示空白畫面。

這無法提供良好的使用者體驗。在這項工作中,您需要新增基本的錯誤處理機制,讓使用者更好地瞭解發生的情況。如果未連線到網際網路,應用程式將顯示連線錯誤圖示。應用程式擷取 MarsProperty 清單時,會顯示載入動畫。
步驟 1:在檢視區塊模型中新增狀態
首先,您會在檢視區塊模型中建立 LiveData,代表網路要求的狀態。需要考慮的狀態有三種:載入、成功和故障。當您等待通話中的資料傳輸至 await() 時,畫面會顯示載入狀態。
- 開啟
overview/OverviewViewModel.kt。然後在檔案頂端 (匯入之後、類別定義之前) 新增enum,代表所有可用狀態:
enum class MarsApiStatus { LOADING, ERROR, DONE }- 在整個
OverviewViewModel類別中,將內部和外部_response即時資料定義重新命名為_status。由於您在本程式碼研究室稍早新增了_propertiesLiveData的支援功能,因此完整的網路服務回應一直未派上用場。您需要在此處使用LiveData追蹤目前狀態,因此只要重新命名現有變數即可。
此外,請將類型從 String 變更為 MarsApiStatus.
private val _status = MutableLiveData<MarsApiStatus>()
val status: LiveData<MarsApiStatus>
get() = _status- 向下捲動至
getMarsRealEstateProperties()方法,並將_response更新為_status。將"Success"字串變更為MarsApiStatus.DONE狀態,並將"Failure"字串變更為MarsApiStatus.ERROR。 - 在
try {}區塊頂端呼叫await()之前,新增MarsApiStatus.LOADING狀態。這是協同程式執行期間以及您在等待資料時的初始狀態。現在,完整的try/catch {}區塊如下所示:
try {
_status.value = MarsApiStatus.LOADING
var listResult = getPropertiesDeferred.await()
_status.value = MarsApiStatus.DONE
_properties.value = listResult
} catch (e: Exception) {
_status.value = MarsApiStatus.ERROR
}- 在
catch {}區塊中的錯誤狀態之後,將_propertiesLiveData設為空白清單。這會清除RecyclerView。
} catch (e: Exception) {
_status.value = MarsApiStatus.ERROR
_properties.value = ArrayList()
}步驟 2:為 ImageView 狀態新增繫結轉接器
現在您在檢視模型中已有狀態,但這只是一組狀態。如何讓應用程式顯示這項資訊?在這個步驟中,您會使用與資料繫結連結的 ImageView,顯示載入和錯誤狀態的圖示。如果應用程式處於載入狀態或錯誤狀態,則應顯示 ImageView。應用程式載入完畢後,應不再顯示 ImageView。
- 開啟
BindingAdapters.kt。新增名為bindStatus()的新繫結轉接器,以ImageView和MarsApiStatus值做為引數。依要求匯入com.example.android.marsrealestate.overview.MarsApiStatus。
@BindingAdapter("marsApiStatus")
fun bindStatus(statusImageView: ImageView,
status: MarsApiStatus?) {
}- 在
bindStatus()方法中新增when {},即可在不同狀態之間切換。
when (status) {
}- 在
when {}中,新增載入狀態的案例 (MarsApiStatus.LOADING)。對於這個狀態,請將ImageView設為顯示,並指派載入動畫。這個動畫可繪項目與先前工作中 Glide 採用的可繪項目相同。依要求匯入android.view.View。
when (status) {
MarsApiStatus.LOADING -> {
statusImageView.visibility = View.VISIBLE
statusImageView.setImageResource(R.drawable.loading_animation)
}
}- 新增錯誤狀態的案例,即
MarsApiStatus.ERROR。如同LOADING狀態,請將狀態ImageView設為顯示,並重複使用連線錯誤可繪項目。
MarsApiStatus.ERROR -> {
statusImageView.visibility = View.VISIBLE
statusImageView.setImageResource(R.drawable.ic_connection_error)
}- 新增已完成狀態的案例,即
MarsApiStatus.DONE。您收到了正確的回應,請關閉狀態ImageView的瀏覽權限以隱藏該狀態。
MarsApiStatus.DONE -> {
statusImageView.visibility = View.GONE
}步驟 3:將狀態 ImageView 新增至版面配置
- 開啟
res/layout/fragment_overview.xml。在RecyclerView元素下方的ConstraintLayout內,新增下方顯示的ImageView。
這個ImageView的限制與RecyclerView相同。不過,所設寬度和高度會使用wrap_content將圖片置中,而不是延展圖片來填滿檢視畫面。另請注意app:marsApiStatus屬性,當檢視區塊模型中的狀態屬性變更時,該屬性會讓檢視區塊呼叫BindingAdapter。
<ImageView
android:id="@+id/status_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:marsApiStatus="@{viewModel.status}" />- 在模擬器或裝置上開啟飛航模式,模擬網路連線中斷。接著編譯並執行應用程式,請注意,畫面上會顯示錯誤圖片:

- 輕觸返回按鈕即可關閉應用程式,並關閉飛航模式。使用「最近使用」畫面返回應用程式。當應用程式查詢網路服務時,圖片開始載入之前,畫面上可能會極短暫地顯示載入旋轉圖示,具體視您的網路連線速度而定。
Android Studio 專案:MarsRealEstateGrid
- 如要簡化圖片管理程序,請使用 Glide 程式庫,在應用程式中下載、緩衝處理、解碼及快取圖片。
- 如要從網際網路載入圖片,Glide 需要兩項資訊:圖片的網址,以及要放置圖片的
ImageView物件。如要指定這些選項,請搭配 Glide 使用load()和into()方法。 - 繫結轉接器是一種擴充方法,顯示在檢視畫面與檢視畫面的繫結資料之間。資料變更時,繫結轉接器會提供自訂行為,例如呼叫 Glide 將網址中的圖片載入
ImageView。 - 繫結轉接器是擴充方法,附有
@BindingAdapter註解。 - 如要為 Glide 要求新增選項,請使用
apply()方法。舉例來說,使用apply()和placeholder()指定載入中的可繪項目,並使用apply()和error()指定錯誤的可繪項目。 - 如要製作圖片格線,請將
RecyclerView與GridLayoutManager搭配使用。 - 如要在屬性變更時更新屬性清單,請使用
RecyclerView和版面配置之間的繫結轉接器。
Udacity 課程:
Android 開發人員說明文件:
其他:
本節列出的作業可由課程講師指派給學習本程式碼研究室的學員。講師可自由採取以下行動:
- 視需要指派作業。
- 告知學員如何繳交作業。
- 為作業評分。
講師可以視需求使用全部或部分建議內容,也可以自由指派任何其他合適的作業。
如果您是自行學習本程式碼研究室,不妨利用這些作業驗收學習成果。
回答以下問題
第 1 題
你會使用哪一種 Glide 方法來表示會包含已載入圖片的 ImageView?
▢ into()
▢ with()
▢ imageview()
▢ apply()
第 2 題
如何指定在載入 Glide 時顯示的預留位置圖片?
▢ 搭配可繪項目使用 into() 方法。
▢ 使用 RequestOptions(),並呼叫包含可繪項目的 placeholder() 方法。
▢ 將 Glide.placeholder 屬性指派給可繪項目。
▢ 使用 RequestOptions(),並呼叫包含可繪項目的 loadingImage() 方法。
第 3 題
要如何指出方法實為繫結轉接器?
▢ 呼叫 LiveData 的 setBindingAdapter() 方法。
▢ 將方法置入名為 BindingAdapters.kt 的 Kotlin 檔案。
▢ 在 XML 版面配置中使用 android:adapter 屬性。
▢ 使用 @BindingAdapter 為方法加上註解。
開始下一個課程:
如要查看本課程其他程式碼研究室的連結,請參閱 Android Kotlin 基礎知識程式碼研究室登陸頁面。