Android 自定義Binding Adapter實(shí)戰(zhàn)應(yīng)用及作用詳解
1. Binding Adapter 的基本概念和作用
Binding Adapter 是一個(gè)橋梁,它允許你在 XML 布局文件中,將自定義的屬性(例如 app:image_corners_uri)與 Kotlin/Java 代碼中的方法綁定起來。它解決了 Android 默認(rèn)的 Data Binding 無法處理復(fù)雜邏輯或自定義 View 屬性的問題。
class DataBindingAdapter {
companion object {
@BindingAdapter("media_source_icon", "media_source_name")
@JvmStatic
fun setMediaSourceInfo(view: MediaSourceBar, drawable: Drawable?, name: String?) {
name?.let { view.setMediaSourceName(it) }
drawable?.let { view.setMediaSourceIcon(it) }
}
@BindingAdapter("media_source_right_button")
@JvmStatic
fun setMediaSourceRightButton(view: MediaSourceBar, rotate: Boolean?) {
rotate?.let { view.setMediaSourceRightButton(it) }
}
@BindingAdapter("data")
@JvmStatic
fun bindRecyclerView(
recyclerView: Recyclerview,
list: MutableList<ListItem>?,
) {
val adapter = recyclerView.adapter
if (adapter is RecyclerViewListAdapter) {
list?.let { adapter.submitList(it) }
}
}
@BindingAdapter(value = ["media_metadata", "media_source"], requireAll = false)
@JvmStatic
fun bindMediaMetadataInfo(
simpleMediaView: PlayInfoView,
mediaMetadata: MediaMetadata?,
mediaSource: ServiceBean?
) {
simpleMediaView.setMediaMetadata(mediaMetadata)
if (mediaSource?.packageName in MediaBrowserManager.musicMediaSourceServices) {
simpleMediaView.setMediaServiceBean(mediaSource)
} else {
simpleMediaView.setMediaServiceBean(null)
}
}
@BindingAdapter("duration", "progress", requireAll = false)
@JvmStatic
fun bindMediaMetadataProgress(
simpleMediaView: PlayInfoView,
duration: Long?,
progress: Long?
) {
simpleMediaView.setProgress(duration, progress)
}
@BindingAdapter("player_commands", requireAll = false)
@JvmStatic
fun bindMediaMetadataCommands(
simpleMediaView: PlayInfoView,
commands: Player.Commands?,
) {
simpleMediaView.setPlayerCommands(commands)
}
@BindingAdapter("isPlaying", requireAll = false)
@JvmStatic
fun bindMediaMetadataPlayback(
view: View,
isPlaying: Boolean?,
) {
if (view is PlayInfoView) {
view.setPlayback(isPlaying)
}
if (view is tech.jidouauto.component.widgets.basic.ImageView) {
if (isPlaying == true) {
view.setImageResource(com.jidouauto.mediacenter.R.drawable.item_icon_pause)
} else {
view.setImageResource(com.jidouauto.mediacenter.R.drawable.item_icon_play)
}
}
}
@BindingAdapter("playMode", requireAll = false)
@JvmStatic
fun bindPlayMode(
simpleMediaView: PlayInfoView,
mode: PlayMode?
) {
if (mode != null) {
simpleMediaView.setPlayMode(mode)
}
}
@BindingAdapter("type")
@JvmStatic
fun setType(view: PlayInfoView, type: Int) {
view.setType(type)
}
@BindingAdapter("discType")
@JvmStatic
fun setDiscType(view: PlayInfoView, type: Int) {
view.setDiscType(type)
}
@BindingAdapter("image_corners_uri", "image_radius", requireAll = false)
@JvmStatic
fun imageUri(view: tech.jidouauto.component.widgets.basic.ImageView, uri: Any?, radius: Int?) {
uri?.let {
val imageResource = ImageResource.Remote(
uri,
transformationType = IImageLoader.ImageTransformationType.RoundCorners(radius?.dp ?: 24.dp),
placeholder = com.jidouauto.mediacenter.R.drawable.icon_placeholder,
error = com.jidouauto.mediacenter.R.drawable.icon_placeholder
)
view.imageSource = imageResource
}
}
@BindingAdapter("image_cycle_uri", requireAll = false)
@JvmStatic
fun cycleImageUri(view: tech.jidouauto.component.widgets.basic.ImageView, uri: Any?) {
uri?.let {
val imageResource = ImageResource.Remote(
uri,
transformationType = IImageLoader.ImageTransformationType.CircleCrop,
placeholder = com.jidouauto.mediacenter.R.drawable.icon_placeholder_circle,
error = com.jidouauto.mediacenter.R.drawable.icon_placeholder_circle
)
view.imageSource = imageResource
}
}
@BindingAdapter("player_album_image_cover", requireAll = false)
@JvmStatic
fun playerAlbumImageCover(
view: tech.jidouauto.component.widgets.basic.ImageView,
uri: Any?
) {
}
@BindingAdapter("banner_data", requireAll = false)
@JvmStatic
fun bindBannerViewData(
view: TopBannerCarouselPager,
data: MainBannerItem?,
) {
Logger.info("bind main banner data=${data?.items}")
if (data == null) return
view.setAdapter(TopBannerCarouselPager.Adapter(data.items, data.itemOnClick))
}
@BindingAdapter("show_background", requireAll = false)
@JvmStatic
fun showBackGround(view: View, isShow: Boolean) {
}
/**
* 控制Lottie動(dòng)畫的播放狀態(tài)
* @param view LottieAnimationView實(shí)例
* @param isPlaying 是否正在播放(true:播放,false:暫停)
*/
@BindingAdapter("lottie_playing_state")
@JvmStatic
fun controlLottieAnimation(view: LottieAnimationView, isPlaying: Boolean?) {
isPlaying?.let {
if (it) {
// 如果需要播放且當(dāng)前未播放,則開始/恢復(fù)動(dòng)畫
if (!view.isAnimating) {
view.playAnimation()
}
} else {
// 如果需要暫停且當(dāng)前正在播放,則暫停動(dòng)畫
if (view.isAnimating) {
view.pauseAnimation()
}
}
}
}
/**
* 可選:控制Lottie動(dòng)畫的可見性(根據(jù)播放狀態(tài))
* 當(dāng)播放時(shí)顯示動(dòng)畫,暫停時(shí)隱藏
*/
@BindingAdapter("lottie_visible_with_playing")
@JvmStatic
fun setLottieVisibilityWithPlaying(view: LottieAnimationView, isPlaying: Boolean?) {
view.visibility = if (isPlaying == true) View.VISIBLE else View.GONE
}
}
} 在這份代碼中,@BindingAdapter 注解就是關(guān)鍵。它告訴 Data Binding 編譯器,當(dāng) XML 中使用了該注解中定義的屬性時(shí),應(yīng)該調(diào)用被注解的方法。
例如:@BindingAdapter("media_source_icon", "media_source_name"):定義了兩個(gè)屬性,media_source_icon 和 media_source_name。當(dāng) XML 中同時(shí)使用這兩個(gè)屬性時(shí),會(huì)調(diào)用 setMediaSourceInfo 方法。
2. 常見應(yīng)用場(chǎng)景與代碼分析
這份代碼覆蓋了多種常見的 Binding Adapter 應(yīng)用場(chǎng)景,我們可以逐一分析:
2.1. 綁定簡(jiǎn)單屬性和多個(gè)屬性
setMediaSourceInfo 方法:
注解: @BindingAdapter("media_source_icon", "media_source_name")
應(yīng)用: 將 Drawable 和 String 類型的數(shù)據(jù)綁定到 MediaSourceBar 這個(gè)自定義 View 上,分別設(shè)置圖標(biāo)和名稱。
知識(shí)點(diǎn): @BindingAdapter 注解可以接收多個(gè)屬性名,當(dāng)這些屬性都在 XML 中出現(xiàn)時(shí),被注解的方法會(huì)被調(diào)用。方法參數(shù)的順序和類型必須與屬性值匹配。
setMediaSourceRightButton 方法:
注解: @BindingAdapter("media_source_right_button")
應(yīng)用: 將一個(gè) Boolean 值綁定到 MediaSourceBar 的一個(gè)按鈕上,控制其旋轉(zhuǎn)狀態(tài)。
知識(shí)點(diǎn): 展示了如何綁定單個(gè)自定義屬性,將一個(gè)布爾值直接傳遞給 View 的方法。
2.2. 處理列表數(shù)據(jù)綁定到 RecyclerView
bindRecyclerView 方法:
注解: @BindingAdapter("data")
應(yīng)用: 將一個(gè) MutableList<ListItem> 數(shù)據(jù)列表直接綁定到 RecyclerView。
知識(shí)點(diǎn): 這個(gè)方法非常實(shí)用,它通過檢查 RecyclerView 的 adapter 類型(確保是 RecyclerViewListAdapter),然后調(diào)用 adapter.submitList() 來更新數(shù)據(jù)。這在 ViewModel 中處理列表數(shù)據(jù)時(shí)非常方便,只需在 XML 中設(shè)置 app:data="@{viewModel.myList}",就能實(shí)現(xiàn)列表的自動(dòng)更新。
2.3. 綁定復(fù)雜對(duì)象和多參數(shù)
bindMediaMetadataInfo 方法:
注解: @BindingAdapter(value = ["media_metadata", "media_source"], requireAll = false)
應(yīng)用: 將 MediaMetadata 和 ServiceBean 兩個(gè)復(fù)雜的對(duì)象綁定到 PlayInfoView 上。
知識(shí)點(diǎn):
value = [...]:用于定義多個(gè)屬性。
requireAll = false:這是一個(gè)重要的參數(shù)。它表示這些屬性不必同時(shí)出現(xiàn)在 XML 中。如果設(shè)置為 true(默認(rèn)),只有當(dāng) XML 中同時(shí)包含了所有屬性時(shí),該方法才會(huì)被調(diào)用。設(shè)置為 false 意味著只要其中一個(gè)屬性存在,方法就會(huì)被調(diào)用。
方法中的邏輯展示了如何根據(jù) mediaSource.packageName 進(jìn)行條件判斷,然后設(shè)置不同的 View 狀態(tài),這是 Binding Adapter 中處理復(fù)雜邏輯的常見方式。
2.4. 綁定圖片加載庫
imageUri 和 cycleImageUri 方法:
注解: @BindingAdapter("image_corners_uri", "image_radius", requireAll = false) 和 @BindingAdapter("image_cycle_uri", requireAll = false)
應(yīng)用: 加載遠(yuǎn)程圖片 URL(URI),并根據(jù)不同的屬性進(jìn)行不同的處理。image_corners_uri 用于加載圓角圖片,而 image_cycle_uri 用于加載圓形圖片。
知識(shí)點(diǎn): 這兩個(gè)方法是 Binding Adapter 最常見的用途之一。它們將圖片加載庫(如 Glide、Picasso 或你代碼中的 ImageResource.Remote)的復(fù)雜調(diào)用邏輯封裝起來,讓開發(fā)者在 XML 中只需簡(jiǎn)單地提供一個(gè) URL 即可,大大簡(jiǎn)化了 View 的使用。同時(shí),它還演示了如何處理占位符和錯(cuò)誤圖片。
2.5. 條件判斷和多類型 View 處理
bindMediaMetadataPlayback 方法:
注解: @BindingAdapter("isPlaying", requireAll = false)
應(yīng)用: 根據(jù) isPlaying 的布爾值,改變不同 View 的狀態(tài)。
知識(shí)點(diǎn):方法參數(shù)中的 View 類型非常通用。
方法內(nèi)部使用 if (view is PlayInfoView) 和 if (view is tech.jidouauto.component.widgets.basic.ImageView) 進(jìn)行 類型判斷。這允許同一個(gè) Binding Adapter 處理不同類型的 View,根據(jù) View 的具體類型執(zhí)行不同的邏輯。例如,如果是 PlayInfoView 就設(shè)置播放狀態(tài),如果是 ImageView 就改變圖標(biāo)。
3.@JvmStatic和companion object
@JvmStatic: 這是一個(gè) Kotlin 注解,用于標(biāo)記一個(gè)方法為靜態(tài)方法。在 companion object 中使用此注解后,該方法可以像 Java 的靜態(tài)方法一樣,通過類名直接調(diào)用,這正是 Data Binding 編譯器所要求的。
companion object: Kotlin 中的伴生對(duì)象,用于存放與類相關(guān)的靜態(tài)成員。將所有 Binding Adapter 方法放在 companion object 中是 Kotlin 的最佳實(shí)踐。
OutlineProvider.kt
OutlineProvider 類是一個(gè)自定義的 ViewOutlineProvider,它的主要作用是為 View 設(shè)置圓角裁剪(clipping)效果。它接收 CornerType 和 radius 作為參數(shù),然后根據(jù)這些參數(shù)生成一個(gè) Path,并用它來定義 View 的輪廓(outline)。這使得開發(fā)者可以在不修改 View 背景或使用其他復(fù)雜方法的情況下,輕松地為 View 的特定角或所有角設(shè)置圓角效果。
CornerType枚舉定義了九種不同的圓角類型,包括:ALL: 所有四個(gè)角都設(shè)置圓角。TOP_LEFT,TOP_RIGHT,BOTTOM_LEFT,BOTTOM_RIGHT: 僅設(shè)置單個(gè)角。TOP,BOTTOM,LEFT,RIGHT: 設(shè)置特定邊上的兩個(gè)角。
getOutline方法是核心邏輯所在,它根據(jù)cornerType和radius的值創(chuàng)建一個(gè)floatArray,該數(shù)組用于Path的addRoundRect方法來創(chuàng)建帶有指定圓角的矩形路徑。最后,它使用outline.setPath(path)將這個(gè)路徑應(yīng)用到 View 的輪廓上。
DatabindingAdapter.kt
DatabindingAdapter 類是一個(gè)包含大量靜態(tài) BindingAdapter 方法的集合,這些方法用于在 XML 布局文件中實(shí)現(xiàn)自定義屬性和數(shù)據(jù)綁定。它的核心作用是:
- 圖片加載: 提供了多種方法(如
setImageUrl、setCircleImageUrl、setIqiyiSpecifiedSizeImageUrl)來使用 Glide 庫加載圖片。這些方法支持處理不同的圖片資源類型(ID、Drawable、URI),設(shè)置占位圖、圓角半徑、高斯模糊等效果。 - UI 控件屬性設(shè)置: 提供了許多用于設(shè)置各種 UI 控件屬性的方法,例如:
bindTabLayoutTabs: 動(dòng)態(tài)綁定和設(shè)置TabLayout的 Tab。setLayoutHeight,layoutMarginTop等: 設(shè)置 View 的布局參數(shù)(如高度、邊距)。setQrcodeStatus: 設(shè)置QrcodeScreenView的狀態(tài)和內(nèi)容。setXimalayaAlbumTags: 根據(jù)媒體項(xiàng)的數(shù)據(jù),動(dòng)態(tài)顯示喜馬拉雅的VIP、付費(fèi)、精品等標(biāo)簽圖標(biāo)。setIqyNormalModelTag: 根據(jù)媒體項(xiàng)數(shù)據(jù),動(dòng)態(tài)顯示愛奇藝的VIP、獨(dú)家等標(biāo)簽圖標(biāo)。setOperationPanelItemActivedDisabled: 管理操作面板項(xiàng)的激活和禁用狀態(tài)。strikeThrough: 為TextView的文本添加刪除線效果。
- 動(dòng)畫控制: 提供了用于控制 View 顯示和隱藏動(dòng)畫的方法,例如
setPopupOpenAnimation、setCancelAnimation等。 - 邏輯封裝: 將復(fù)雜的邏輯(如根據(jù)媒體數(shù)據(jù)判斷顯示哪個(gè)標(biāo)簽圖標(biāo))封裝在 BindingAdapter 方法中,使得 XML 布局文件更加簡(jiǎn)潔和易讀。
BindingResourceUtil.kt
BindingResourceUtil 是一個(gè)工具類,包含了一系列靜態(tài)方法,用于將數(shù)據(jù)模型中的原始值(如浮點(diǎn)數(shù)、字符串、枚舉)轉(zhuǎn)換為可用于數(shù)據(jù)綁定的資源對(duì)象(如 ImageResource、TextResource)。它的核心作用是:
- 數(shù)據(jù)到資源的轉(zhuǎn)換: 提供了將邏輯值轉(zhuǎn)換為 UI 資源的方法,例如:
playbackSpeedIcon: 根據(jù)播放速度的浮點(diǎn)值返回相應(yīng)的圖標(biāo)資源 ID。definitionText: 根據(jù)視頻清晰度的字符串返回相應(yīng)的文本資源 ID。ximalayaDownloadIcon: 根據(jù)喜馬拉雅媒體項(xiàng)的下載類型返回相應(yīng)的下載圖標(biāo)資源 ID。
- 多源媒體適配: 提供了針對(duì)不同媒體源(酷我、喜馬拉雅、樂聽)的資源轉(zhuǎn)換方法。例如,
playingCoverPlaceHolder會(huì)根據(jù)mediaId判斷媒體源,并返回相應(yīng)的占位圖。 - 文案和狀態(tài)轉(zhuǎn)換: 將邏輯狀態(tài)(如下載狀態(tài)、二維碼狀態(tài))轉(zhuǎn)換為用戶可讀的文本資源 ID。例如,
downloadDisabledReason根據(jù)下載狀態(tài)返回相應(yīng)的禁用原因文本。
DataBindingConvertor.java
DataBindingConvertor 是一個(gè)簡(jiǎn)單的 Java 類,它使用 @BindingConversion 注解定義了一些類型轉(zhuǎn)換方法。它的核心作用是:
- 自動(dòng)類型轉(zhuǎn)換: 實(shí)現(xiàn)了 Android Data Binding 框架中的自動(dòng)類型轉(zhuǎn)換功能。這使得開發(fā)者可以在 XML 布局文件中直接使用原始類型(如
int、CharSequence、Drawable、Uri),而無需手動(dòng)將其包裝成TextResource或ImageResource。 - 簡(jiǎn)化 XML 綁定: 例如,當(dāng)你在 XML 中將一個(gè)
int類型的資源 ID 綁定給一個(gè)需要TextResource的屬性時(shí),convertTextResource(int id)方法會(huì)自動(dòng)被調(diào)用,完成類型轉(zhuǎn)換。 - 處理特定數(shù)據(jù)模型: 提供了針對(duì)
QrCodeTokenInfo、OrderBean和IqiyiOrderBean的轉(zhuǎn)換方法,用于從這些數(shù)據(jù)模型中提取二維碼 URL。
DataBindingNavigationUtil.kt
DataBindingNavigationUtil 是一個(gè)工具類,專門用于處理與導(dǎo)航相關(guān)的邏輯。它的核心作用是:
- Fragment 和 Activity 導(dǎo)航: 提供了
openFragment等方法,用于在不同的上下文(Activity或Fragment)中打開新的 Fragment。 - 業(yè)務(wù)邏輯封裝: 封裝了與具體業(yè)務(wù)相關(guān)的導(dǎo)航邏輯,例如:
kuwoVipPayFragment,ximalayaLoginFragment: 創(chuàng)建并返回特定媒體源的 VIP 支付或登錄 Fragment。buildXimalayaPayDialog: 根據(jù)喜馬拉雅媒體項(xiàng)的購買類型,構(gòu)建并返回一個(gè)定制的購買彈窗對(duì)話框。ximalayaBuyFragment: 根據(jù)登錄狀態(tài)和媒體項(xiàng)的購買類型,決定并返回正確的 Fragment(登錄、VIP 購買或?qū)]嬞徺I)。
- 播放控制和彈窗: 提供了處理播放相關(guān)彈窗和 Fragment 的方法,例如
showRecognizeDialog用于顯示正在識(shí)別歌曲的彈窗,switchLrcFragment用于切換歌詞視圖。 - 上下文處理: 包含了一些輔助方法,用于在
FragmentContextWrapper中獲取實(shí)際的Fragment對(duì)象,以及處理上下文的層級(jí)關(guān)系。這使得導(dǎo)航工具類可以在不同類型的上下文中通用。
提供的這五個(gè)類是為了實(shí)現(xiàn)一套強(qiáng)大、靈活且易于維護(hù)的數(shù)據(jù)綁定和UI構(gòu)建框架,尤其是在處理多媒體應(yīng)用中常見的復(fù)雜UI和動(dòng)態(tài)數(shù)據(jù)時(shí)。這種設(shè)計(jì)模式遵循了許多軟件工程的最佳實(shí)踐,例如關(guān)注點(diǎn)分離、模塊化和代碼復(fù)用。
以下是詳細(xì)解釋為什么要這樣設(shè)計(jì)的理由:
1. 關(guān)注點(diǎn)分離 (Separation of Concerns)
DataBindingConvertor.java和BindingResourceUtil.kt: 這兩個(gè)類負(fù)責(zé)將后端數(shù)據(jù)模型(如MediaMetadataCompat、QrCodeTokenInfo)轉(zhuǎn)換為UI所需的資源類型(如TextResource、ImageResource)或特定的文本格式(如播放速度字符串、二維碼URL)。它們將數(shù)據(jù)處理和格式化的邏輯從視圖層(XML布局)和視圖模型層中分離出來,使得數(shù)據(jù)模型可以保持簡(jiǎn)潔,而不必包含與UI呈現(xiàn)相關(guān)的復(fù)雜邏輯。DatabindingAdapter.kt: 這個(gè)類專門負(fù)責(zé)將數(shù)據(jù)綁定到實(shí)際的UI組件上。它處理諸如圖片加載(使用Glide)、設(shè)置圓角、動(dòng)態(tài)調(diào)整布局、添加動(dòng)畫等所有與視圖操作相關(guān)的細(xì)節(jié)。這使得XML布局文件只專注于聲明性的UI結(jié)構(gòu),而不需要包含任何實(shí)現(xiàn)細(xì)節(jié)。OutlineProvider.kt: 這個(gè)類將View的輪廓裁剪邏輯獨(dú)立出來,專門用于為View設(shè)置不同類型的圓角。這使得圓角效果可以被復(fù)用,并且與View的背景、內(nèi)容等其他屬性完全解耦。
2. 代碼復(fù)用和模塊化
DataBindingConvertor.java和BindingResourceUtil.kt: 許多UI元素(如播放速度圖標(biāo)、下載按鈕圖標(biāo))在應(yīng)用的多個(gè)地方都會(huì)用到。將這些轉(zhuǎn)換邏輯集中在這兩個(gè)工具類中,可以避免在每個(gè)地方都重復(fù)編寫相同的when或if-else語句來判斷狀態(tài)和選擇資源。DatabindingAdapter.kt: 通過創(chuàng)建自定義的BindingAdapter,可以在多個(gè)XML布局文件中復(fù)用相同的UI綁定邏輯。例如,setImageUrlWithRadius方法可以用于應(yīng)用中任何需要加載帶圓角圖片的ImageView,而無需在每個(gè)布局或Fragment中手動(dòng)調(diào)用 Glide。OutlineProvider.kt: 同樣的,如果多個(gè) View 需要相同的圓角效果(例如,所有專輯封面都需要四個(gè)角的圓角),只需在 XML 中通過數(shù)據(jù)綁定設(shè)置OutlineProvider即可,無需在每個(gè)地方都創(chuàng)建新的ViewOutlineProvider對(duì)象。
3. 易于維護(hù)和擴(kuò)展
- 清晰的職責(zé): 當(dāng)需要修改某個(gè)功能時(shí),開發(fā)者可以快速定位到相應(yīng)的類。例如,要改變所有播放速度圖標(biāo)的樣式,只需修改
BindingResourceUtil.kt中的playbackSpeedIcon方法即可,而無需在多個(gè)文件中尋找和修改代碼。要調(diào)整圖片加載邏輯,只需修改DatabindingAdapter.kt中的 Glide 相關(guān)方法。 - 靈活的導(dǎo)航:
DataBindingNavigationUtil.kt將所有復(fù)雜的導(dǎo)航邏輯(例如,根據(jù)媒體項(xiàng)類型決定打開哪個(gè)支付或登錄Fragment)封裝在一個(gè)地方。這使得在需要修改導(dǎo)航流程時(shí),開發(fā)者只需關(guān)注這個(gè)工具類,而不是在不同的Activity或Fragment中修改分散的startActivity或beginTransaction代碼。 - 適應(yīng)多媒體源: 媒體應(yīng)用通常需要支持多種媒體源(如酷我、喜馬拉雅、愛奇藝)。
BindingResourceUtil.kt中的許多方法都通過判斷mediaId來適配不同的媒體源,并返回相應(yīng)的資源,這使得應(yīng)用能夠輕松地處理多媒體源帶來的差異性。
到此這篇關(guān)于Android 自定義Binding Adapter實(shí)戰(zhàn)應(yīng)用的文章就介紹到這了,更多相關(guān)Android 自定義Binding Adapter內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實(shí)例HandlerThread源碼分析
本篇文章主要給大家通過實(shí)例代碼分析了Android中HandlerThread的用法以及步驟,需要的朋友參考學(xué)習(xí)下吧。2017-12-12
Android使用CardView作為RecyclerView的Item并實(shí)現(xiàn)拖拽和左滑刪除
這篇文章主要介紹了Android使用CardView作為RecyclerView的Item并實(shí)現(xiàn)拖拽和左滑刪除,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11
Android 異步獲取網(wǎng)絡(luò)圖片并處理導(dǎo)致內(nèi)存溢出問題解決方法
Android異步獲取網(wǎng)絡(luò)圖片并處理圖片Out Of Memory內(nèi)存溢出如何解決呢?本文介紹了操作步驟,感興趣的朋友可以了解下或許對(duì)你有所幫助2013-02-02
舉例講解Android應(yīng)用中SimpleAdapter簡(jiǎn)單適配器的使用
這篇文章主要介紹了Android應(yīng)用中SimpleAdapter簡(jiǎn)單適配器的使用例子,SimpleAdapter經(jīng)常在ListView被使用,需要的朋友可以參考下2016-04-04
Android RecycleView 實(shí)現(xiàn)左滑上下分層示例代碼(自定義功能)
這篇文章主要介紹了Android RecycleView 實(shí)現(xiàn)左滑上下分層示例代碼(自定義功能),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-03-03
Rocksdb?Memtable數(shù)據(jù)結(jié)構(gòu)源碼解析
這篇文章主要為大家介紹了Rocksdb?Memtable數(shù)據(jù)結(jié)構(gòu)源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Android Studio報(bào)錯(cuò)unable to access android sdk add-on list解決方案
這篇文章主要介紹了Android Studio報(bào)錯(cuò)unable to access android sdk add-on list解決方案,本文通過多種方式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03
Android View事件分發(fā)和消費(fèi)源碼簡(jiǎn)單理解
這篇文章主要介紹了Android View事件分發(fā)和消費(fèi)源碼簡(jiǎn)單理解的相關(guān)資料,需要的朋友可以參考下2017-07-07

