本程式碼研究室是 Android Kotlin 基礎課程的一部分。使用程式碼研究室逐步完成程式碼課程後,您將能充分發揮本課程的潛能。所有課程程式碼研究室清單均列於 Android Kotlin 基礎程式碼研究室到達網頁。
簡介
在先前的程式碼研究室中,您已學會如何從網路服務取得資料,並將回應剖析為資料物件。在本程式碼研究室中,你可以利用這項知識來載入和顯示網址中的相片。您也可以回顧如何建構 RecyclerView
並使用它在總覽頁面上顯示圖片格線。
須知事項
- 如何建立及使用片段。
- 如何使用架構元件,包括檢視模型、查看模型工廠、轉換和
LiveData
。 - 如何使用 Retrofit 和 Moshi 程式庫從 REST 網路服務擷取 JSON 並將資料剖析為 Kotlin 物件。
- 如何使用
RecyclerView
建構格線版面配置。 Adapter
、ViewHolder
和DiffUtil
的運作方式。
您將會瞭解的內容
- 如何使用 Glide 程式庫載入及顯示網頁網址的圖片。
- 如何使用
RecyclerView
和格狀轉接程式來顯示圖片格線。 - 如何處理圖片下載及顯示時出現的潛在錯誤。
要執行的步驟
- 修改 MarsRealEstate 應用程式以取得 Mars 屬性資料中的圖片網址,然後使用 Glide 載入並顯示該圖片。
- 在應用程式中新增載入動畫和錯誤圖示。
- 使用
RecyclerView
即可顯示包含火星屬性圖片的格線。 - 為
RecyclerView
新增狀態和錯誤處理機制。
在這個程式碼研究室 (及相關的程式碼研究室) 中,您使用了名為 MarsRealEstate 的應用程式,在 Mars 上展示要銷售的房產。應用程式會連線至網際網路伺服器,以擷取和顯示屬性資料,包括價格、是否販售或出租等詳細資料。每個資源代表的圖片都是從 NASA 所拍攝的火星漫遊的實景照片。
您在這個程式碼研究室中建立的應用程式版本會填入總覽頁面,該頁面會顯示圖片方格。這些圖片是應用程式從 Mars 房地產網路服務取得的資源資料中的一部分。您的應用程式會使用 Glide 程式庫載入及顯示圖片,使用 RecyclerView
為圖片建立格線版面配置。此外,應用程式還會妥善處理網路錯誤。
顯示來自網址的相片聽起來可能很簡單,但卻需要很多工程技術才能成功。圖片必須下載、緩衝處理,以及從壓縮格式中解碼為 Android 可使用的圖片。圖片應快取至記憶體內快取或儲存空間型快取,或同時快取至兩者。這需要在低優先順序背景執行緒中完成,這樣 UI 才不會回應。此外,為了獲得最佳網路和 CPU 效能,建議您一次擷取並解碼多張圖片。學習如何從網路有效載入圖片,可能是程式碼研究室本身。
幸好,您可以使用社群開發的 Glide 程式庫下載、緩衝處理、解碼及快取圖片。相較於單純從頭開始完成的工作,滑行作業可以省下許多心力。
滑行基本上需要兩件事情:
- 您要載入並顯示的圖片網址。
- 用來顯示該圖片的
ImageView
物件。
在這項工作中,您會學到如何使用 Glide 顯示房地產網路服務中的單一圖片。您可以在網路服務傳回的屬性清單中,呈現第一個火星屬性的圖片。以下是前後對照的螢幕截圖:
步驟 1:新增 Glide 依附元件
- 從最後一個程式碼研究室開啟 MarsRealEstate 應用程式。(如果您沒有這個應用程式,可以在這裡下載 MarsRealEstateNetwork)。
- 執行應用程式以查看其用途。(內容會顯示在 Tus 上提供假設的資源屬性詳細資料)。
- 開啟 build.gradle (Module: app)。
- 在
dependencies
區段中,為 Glide 程式庫新增這一行:
implementation "com.github.bumptech.glide:glide:$version_glide"
請注意,專案編號已在專案 Gradle 檔案中另行定義。
- 請按一下 [立即同步處理],以新的依附元件重新建立專案。
步驟 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
物件,這項測試會將_property
LiveData
的值設為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
以繫結至property
LiveData
的imgSrcUrl
元件:
android:text="@{viewModel.property.imgSrcUrl}"
- 執行應用程式。
TextView
只會顯示第一個火星資源中的圖片網址。到目前為止,您已經設定完該模式的檢視模式和即時資料。
步驟 3:建立繫結轉接程式並呼叫 Glide
現在,您已經取得要顯示圖片的網址,現在可以開始透過 Glide 載入圖片了。在這個步驟中,您可以使用繫結轉接程式從與 ImageView
相關聯的 XML 屬性中擷取網址,然後使用 Glide 載入圖片。繫結轉接程式是一種位於視圖和繫結資料之間的擴充方法,可在資料變更時提供自訂行為。在這種情況下,自訂行為就是呼叫 Glide,將圖片中的網址載入至 ImageView
。
- 開啟
BindingAdapters.kt
。這個檔案會保留您在應用程式中使用的繫結轉接程式。 - 建立採用
ImageView
和String
做為參數的bindImage()
函式。使用@BindingAdapter
為函式加上註解。當 XML 項目具有imageUrl
屬性時,@BindingAdapter
註解會告知資料繫結您想要這個繫結轉接程式。
可要求匯入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>
- 將
app:imageUrl
屬性新增至ImageView
元素,以使用新的圖片載入繫結轉接程式:
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's 參照等式運算子 (===
)。如果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
。由於您在這個程式碼研究室中,加入了_properties
LiveData
的支援,因此尚未提供完整的網路服務回應。在這裡需要一個LiveData
來追蹤目前的狀態,因此您可以重新命名現有的變數。
另外,請將類型從「String
」改為「MarsApiStatus.
」
private val _status = MutableLiveData<MarsApiStatus>()
val status: LiveData<MarsApiStatus>
get() = _status
- 向下捲動到
getMarsRealEstateProperties()
方法,並一併將_response
更新為_status
。將"Success"
字串變更為MarsApiStatus.DONE
狀態,並將"Failure"
字串變更為MarsApiStatus.ERROR
字串。 - 在呼叫
await()
之前,於try {}
區塊頂端加上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 {}
區塊中的錯誤狀態後,請將_properties
LiveData
設為空白清單。這項操作將會清除RecyclerView
。
} catch (e: Exception) {
_status.value = MarsApiStatus.ERROR
_properties.value = ArrayList()
}
步驟 2:為狀態圖片檢視畫面新增繫結轉接程式
現在,您在「檢視」模型中已有狀態,但其只是一組狀態。如何讓應用程式出現在應用程式中?在這個步驟中,您會使用已連線至資料繫結的 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
設為顯示,並指派載入動畫。這與您在前一項工作中用於滑行時使用的動畫繪圖功能相同。在要求時匯入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 程式庫來下載、緩衝處理、解碼及快取應用程式中的圖片。
- 他必須從網際網路載入圖片中的兩個項目:圖片網址,以及要放置圖片的
ImageView
物件。若要指定這些選項,請搭配 Glide 使用load()
和into()
方法。 - 繫結轉接器是一種擴充方法,顯示在檢視畫面與檢視畫面的繫結資料之間。舉例來說,呼叫 Glide 即可呼叫 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 基礎程式碼程式碼到達網頁。