ยกระดับการเล่นสื่อ: เจาะลึก PreloadManager ของ Media3 - ตอนที่ 2
อ่าน 9 นาที
ยินดีต้อนรับสู่ตอนที่ 2 ของซีรีส์ 3 ตอนเกี่ยวกับการโหลดสื่อล่วงหน้าด้วย Media3 ชุดนี้ออกแบบมาเพื่อแนะนำกระบวนการสร้างประสบการณ์สื่อที่มีการตอบสนองสูงและมีเวลาในการตอบสนองต่ำในแอป Android
- ส่วนที่ 1: การแนะนำการโหลดล่วงหน้าด้วย Media3 ครอบคลุมพื้นฐาน เราได้สำรวจความแตกต่างระหว่าง PreloadConfiguration สำหรับเพลย์ลิสต์แบบง่ายกับ DefaultPreloadManager ที่มีประสิทธิภาพมากกว่าสำหรับอินเทอร์เฟซผู้ใช้แบบไดนามิก คุณได้เรียนรู้วิธีใช้รอบการใช้งาน API ขั้นพื้นฐานแล้ว ได้แก่ การเพิ่มสื่อด้วย add(), การเรียกข้อมูล MediaSource ที่เตรียมไว้ด้วย getMediaSource(), การจัดการลำดับความสำคัญด้วย setCurrentPlayingIndex() และ invalidate() รวมถึงการปล่อยทรัพยากรด้วย remove() และ release()
- ส่วนที่ 2 (โพสต์นี้): ในบล็อกนี้ เราจะสำรวจความสามารถขั้นสูงของ DefaultPreloadManager เราจะพูดถึงวิธีรับข้อมูลเชิงลึกด้วย PreloadManagerListener, การใช้ข้อแนะนำที่พร้อมใช้งานจริง เช่น การแชร์คอมโพเนนต์หลักกับ ExoPlayer และการใช้รูปแบบหน้าต่างเลื่อนเพื่อจัดการหน่วยความจำอย่างมีประสิทธิภาพ
- ส่วนที่ 3: ส่วนสุดท้ายของซีรีส์นี้จะเจาะลึกการผสานรวม PreloadManager กับแคชดิสก์แบบถาวร ซึ่งจะช่วยให้คุณลดการใช้ข้อมูลด้วยการจัดการทรัพยากรและมอบประสบการณ์ที่ราบรื่น
หากคุณเพิ่งเริ่มใช้การโหลดล่วงหน้าใน Media3 เราขอแนะนำอย่างยิ่งให้อ่านส่วนที่ 1 ก่อนดำเนินการต่อ สำหรับผู้ที่พร้อมจะก้าวข้ามพื้นฐานไปอีกขั้น มาดูวิธียกระดับการติดตั้งใช้งานการเล่นสื่อกัน
การฟัง: ดึงข้อมูลวิเคราะห์ด้วย PreloadManagerListener
เมื่อต้องการเปิดตัวฟีเจอร์ในเวอร์ชันที่ใช้งานจริง ในฐานะนักพัฒนาแอป คุณก็คงอยากจะทำความเข้าใจและบันทึกข้อมูลวิเคราะห์ที่อยู่เบื้องหลังฟีเจอร์นั้นด้วย คุณจะมั่นใจได้อย่างไรว่ากลยุทธ์การโหลดล่วงหน้ามีประสิทธิภาพในสภาพแวดล้อมจริง การตอบคำถามนี้ต้องใช้ข้อมูลเกี่ยวกับอัตราความสำเร็จ ความล้มเหลว และประสิทธิภาพ อินเทอร์เฟซ PreloadManagerListener เป็นกลไกหลักในการรวบรวมข้อมูลนี้
PreloadManagerListener มีการเรียกกลับที่สำคัญ 2 รายการซึ่งให้ข้อมูลเชิงลึกที่สำคัญเกี่ยวกับกระบวนการและสถานะการโหลดล่วงหน้า
- onCompleted(MediaItem mediaItem): ระบบจะเรียกใช้ Callback นี้เมื่อคำขอโหลดล่วงหน้าเสร็จสมบูรณ์ตามที่กำหนดโดย TargetPreloadStatusControl
- onError(ข้อผิดพลาด PreloadException): Callback นี้อาจมีประโยชน์สำหรับการแก้ไขข้อบกพร่องและการตรวจสอบ ระบบจะเรียกใช้ฟังก์ชันนี้เมื่อการโหลดล่วงหน้าล้มเหลว โดยจะแสดงข้อยกเว้นที่เกี่ยวข้อง
คุณลงทะเบียน Listener ด้วยการเรียกใช้เมธอดเดียวได้ดังที่แสดงในตัวอย่างโค้ดต่อไปนี้
val preloadManagerListener = object : PreloadManagerListener {
override fun onCompleted(mediaItem: MediaItem) {
// Log success for analytics.
Log.d("PreloadAnalytics", "Preload completed for $mediaItem")
}
override fun onError( preloadError: PreloadException) {
// Log the specific error for debugging and monitoring.
Log.e("PreloadAnalytics", "Preload error ", preloadError)
}
}
preloadManager.addListener(preloadManagerListener)การดึงข้อมูลเชิงลึกจากผู้ฟัง
คุณเชื่อมต่อการเรียกกลับของผู้ฟังเหล่านี้กับไปป์ไลน์การวิเคราะห์ได้ การส่งต่อเหตุการณ์เหล่านี้ไปยังเครื่องมือวิเคราะห์จะช่วยให้คุณตอบคำถามสำคัญๆ ได้ เช่น
- อัตราความสำเร็จในการโหลดล่วงหน้าของเราคืออะไร (อัตราส่วนของเหตุการณ์ onCompleted ต่อความพยายามในการโหลดล่วงหน้าทั้งหมด)
- CDN หรือรูปแบบวิดีโอใดที่มีอัตราข้อผิดพลาดสูงที่สุด (โดยการแยกวิเคราะห์ข้อยกเว้นจาก onError)
- อัตราข้อผิดพลาดในการโหลดล่วงหน้าคืออะไร (อัตราส่วนของเหตุการณ์ onError ต่อจำนวนครั้งที่พยายามโหลดล่วงหน้าทั้งหมด)
ข้อมูลนี้อาจให้ความคิดเห็นเชิงปริมาณเกี่ยวกับกลยุทธ์การโหลดล่วงหน้า ซึ่งจะช่วยให้คุณทำการทดสอบ A/B และปรับปรุงประสบการณ์ของผู้ใช้โดยอิงตามข้อมูลได้ ข้อมูลนี้จะช่วยให้คุณปรับแต่งระยะเวลาการโหลดล่วงหน้าอย่างชาญฉลาด รวมถึงจำนวนวิดีโอที่ต้องการโหลดล่วงหน้าและบัฟเฟอร์ที่คุณจัดสรร
นอกเหนือจากการแก้ไขข้อบกพร่อง: การใช้ onError สำหรับการเปลี่ยน UI กลับอย่างราบรื่น
การโหลดล่วงหน้าที่ไม่สำเร็จเป็นตัวบ่งชี้ที่ชัดเจนว่าผู้ใช้กำลังจะพบเหตุการณ์บัฟเฟอร์ โดย onError Callback จะช่วยให้คุณตอบสนองได้อย่างรวดเร็ว คุณสามารถปรับ UI แทนที่จะบันทึกข้อผิดพลาดเพียงอย่างเดียว เช่น หากวิดีโอถัดไปโหลดล่วงหน้าไม่สำเร็จ แอปพลิเคชันอาจปิดใช้การเล่นอัตโนมัติสำหรับการปัดครั้งถัดไป ซึ่งจะกำหนดให้ผู้ใช้แตะเพื่อเริ่มเล่น
นอกจากนี้ การตรวจสอบประเภท PreloadException ยังช่วยให้คุณกำหนดกลยุทธ์การลองใหม่ที่ชาญฉลาดยิ่งขึ้นได้ แอปสามารถเลือกที่จะนำแหล่งที่มาที่ไม่สำเร็จออกจากเครื่องมือจัดการได้ทันทีตามข้อความแสดงข้อผิดพลาดหรือรหัสสถานะ HTTP คุณจะต้องนำรายการดังกล่าวออกจากสตรีม UI เพื่อไม่ให้ปัญหาการโหลดส่งผลต่อประสบการณ์ของผู้ใช้ นอกจากนี้ คุณยังรับข้อมูลแบบละเอียดเพิ่มเติมจาก PreloadException เช่น HttpDataSourceException เพื่อตรวจสอบข้อผิดพลาดเพิ่มเติมได้ด้วย ดูข้อมูลเพิ่มเติมเกี่ยวกับการแก้ปัญหา ExoPlayer
ระบบบัดดี้: เหตุใดจึงจำเป็นต้องแชร์คอมโพเนนต์กับ ExoPlayer
DefaultPreloadManager และ ExoPlayer ออกแบบมาให้ทำงานร่วมกัน โดยต้องแชร์คอมโพเนนต์หลักหลายรายการเพื่อให้มั่นใจถึงความเสถียรและประสิทธิภาพ หากทำงานด้วยคอมโพเนนต์ที่แยกกันและไม่ได้ประสานงานกัน อาจส่งผลต่อความปลอดภัยของเธรดและความสามารถในการใช้งานแทร็กที่โหลดไว้ล่วงหน้าในเพลเยอร์ เนื่องจากเราต้องตรวจสอบว่าแทร็กที่โหลดไว้ล่วงหน้าควรเล่นในเพลเยอร์ที่ถูกต้อง นอกจากนี้ คอมโพเนนต์ที่แยกกันยังอาจแข่งขันกันเพื่อใช้ทรัพยากรที่มีจำกัด เช่น แบนด์วิดท์เครือข่ายและหน่วยความจำ ซึ่งอาจทำให้ประสิทธิภาพลดลง ส่วนสำคัญของวงจรนี้คือการจัดการการกำจัดที่เหมาะสม โดยลำดับการกำจัดที่แนะนำคือการปล่อย PreloadManager ก่อน แล้วตามด้วย ExoPlayer
DefaultPreloadManager.Builder ออกแบบมาเพื่ออำนวยความสะดวกในการแชร์นี้ และมี API สำหรับสร้างอินสแตนซ์ทั้ง PreloadManager และอินสแตนซ์ของเพลเยอร์ที่ลิงก์ มาดูกันว่าเหตุใดจึงต้องแชร์คอมโพเนนต์ต่างๆ เช่น BandwidthMeter, LoadControl, TrackSelector, Looper ดูภาพของวิธีที่คอมโพเนนต์เหล่านี้โต้ตอบกับการเล่น ExoPlayer
การป้องกันไม่ให้แบนด์วิดท์ขัดแย้งกับ BandwidthMeter ที่แชร์
BandwidthMeter จะประมาณแบนด์วิดท์เครือข่ายที่ใช้ได้โดยอิงตามอัตราการโอนข้อมูลที่ผ่านมา หาก PreloadManager และเพลเยอร์ใช้อินสแตนซ์แยกกัน ทั้ง 2 จะไม่ทราบกิจกรรมเครือข่ายของกันและกัน ซึ่งอาจทําให้เกิดสถานการณ์ที่ล้มเหลวได้ ตัวอย่างเช่น ลองพิจารณาสถานการณ์ที่ผู้ใช้กำลังดูวิดีโออยู่ การเชื่อมต่อเครือข่ายมีประสิทธิภาพลดลง และ MediaSource ที่โหลดล่วงหน้าจะเริ่มดาวน์โหลดวิดีโอในอนาคตอย่างรวดเร็วพร้อมกัน กิจกรรมของ MediaSource ที่โหลดล่วงหน้าจะใช้แบนด์วิดท์ที่เพลเยอร์ที่ใช้งานอยู่ต้องการ ซึ่งทำให้วิดีโอที่กำลังเล่นอยู่หยุดชะงัก การหยุดชะงักระหว่างการเล่นเป็นความล้มเหลวที่สำคัญในด้านประสบการณ์ของผู้ใช้
การแชร์ BandwidthMeter รายการเดียวทำให้ TrackSelector สามารถเลือกแทร็กที่มีคุณภาพสูงสุดตามสภาพเครือข่ายปัจจุบันและสถานะของบัฟเฟอร์ในระหว่างการโหลดล่วงหน้าหรือการเล่น จากนั้นจะสามารถตัดสินใจอย่างชาญฉลาดเพื่อปกป้องเซสชันการเล่นที่ใช้งานอยู่และมอบประสบการณ์ที่ราบรื่น
preloadManagerBuilder.setBandwidthMeter(customBandwidthMeter)
รับประกันความสอดคล้องกับคอมโพเนนต์ LoadControl, TrackSelector, Renderer ที่แชร์ของ ExoPlayer
- LoadControl: คอมโพเนนต์นี้กำหนดนโยบายการบัฟเฟอร์ เช่น จำนวนข้อมูลที่จะบัฟเฟอร์ก่อนเริ่มเล่น และเวลาที่จะเริ่มหรือหยุดโหลดข้อมูลเพิ่มเติม การแชร์ LoadControl ช่วยให้มั่นใจได้ว่าการใช้หน่วยความจำของเพลเยอร์และ PreloadManager จะเป็นไปตามกลยุทธ์การบัฟเฟอร์แบบประสานงานเดียวทั้งในสื่อที่โหลดล่วงหน้าและสื่อที่เล่นอยู่ ซึ่งจะช่วยป้องกันการแย่งชิงทรัพยากร คุณจะต้องจัดสรรขนาดบัฟเฟอร์อย่างชาญฉลาดโดยประสานงานกับจำนวนรายการที่คุณโหลดล่วงหน้าและระยะเวลา เพื่อให้มั่นใจถึงความสอดคล้องกัน ในกรณีที่มีการแข่งขันกัน วิดีโอเพลเยอร์จะจัดลำดับความสำคัญของการเล่นรายการปัจจุบันที่แสดงบนหน้าจอ เมื่อใช้ LoadControl ที่แชร์ ตัวจัดการการโหลดล่วงหน้าจะโหลดล่วงหน้าต่อไปตราบใดที่ไบต์บัฟเฟอร์เป้าหมายที่จัดสรรไว้สำหรับการโหลดล่วงหน้ายังไม่ถึงขีดจำกัดบน โดยจะไม่รอจนกว่าการโหลดสำหรับการเล่นจะเสร็จสิ้น
หมายเหตุ: การแชร์ LoadControl ใน Media3 (1.8) เวอร์ชันล่าสุดช่วยให้มั่นใจได้ว่า Allocator จะแชร์กับ PreloadManager และเพลเยอร์ได้อย่างถูกต้อง การใช้ LoadControl เพื่อควบคุมการโหลดล่วงหน้าอย่างมีประสิทธิภาพเป็นฟีเจอร์ที่จะพร้อมใช้งานใน Media3 1.9 รุ่นถัดไป
preloadManagerBuilder.setLoadControl(customLoadControl)
- TrackSelector: คอมโพเนนต์นี้มีหน้าที่เลือกแทร็ก (เช่น วิดีโอที่มีความละเอียดหนึ่งๆ เสียงในภาษาหนึ่งๆ) ที่จะโหลดและเล่น การแชร์จะช่วยให้มั่นใจว่าแทร็กที่เลือกไว้ระหว่างการโหลดล่วงหน้าเป็นแทร็กเดียวกันกับที่เพลเยอร์จะใช้ วิธีนี้จะช่วยหลีกเลี่ยงสถานการณ์ที่สิ้นเปลืองซึ่งมีการโหลดแทร็กวิดีโอ 480p ไว้ล่วงหน้า แต่โปรแกรมเล่นกลับทิ้งแทร็กนั้นทันทีและดึงแทร็ก 720p มาแทนเมื่อเล่น< br /> ตัวจัดการการโหลดล่วงหน้าไม่ควรใช้อินสแตนซ์เดียวกันของ TrackSelector กับโปรแกรมเล่น แต่ควรใช้ instance อื่นของ TrackSelector แต่เป็นการติดตั้งใช้งานเดียวกัน เราจึงตั้งค่า TrackSelectorFactory แทนที่จะเป็น TrackSelector ใน DefaultPreloadManager.Builder
preloadManagerBuilder.setTrackSelectorFactory(customTrackSelectorFactory)
- โปรแกรมแสดงผล: คอมโพเนนต์นี้มีหน้าที่ทำความเข้าใจความสามารถของเพลเยอร์โดยไม่ต้องสร้างโปรแกรมแสดงผลแบบเต็ม โดยจะตรวจสอบพิมพ์เขียวนี้เพื่อดูว่าเพลเยอร์สุดท้ายจะรองรับรูปแบบวิดีโอ เสียง และข้อความใดบ้าง ซึ่งช่วยให้สามารถเลือกและดาวน์โหลดเฉพาะแทร็กสื่อที่เข้ากันได้อย่างชาญฉลาด และป้องกันไม่ให้แบนด์วิดท์สูญเปล่าไปกับเนื้อหาที่เพลเยอร์เล่นไม่ได้
preloadManagerBuilder.setRenderersFactory(customRenderersFactory)
อ่านเกี่ยวกับคอมโพเนนต์ Exoplayer เพิ่มเติม
กฎเหล็ก: Playback Looper ทั่วไปที่ใช้ได้กับทุกอย่าง
คุณระบุเธรดที่เข้าถึงอินสแตนซ์ ExoPlayer ได้อย่างชัดเจนโดยส่ง Looper เมื่อสร้างเพลเยอร์ คุณสามารถค้นหา Looper ของเธรดที่ต้องเข้าถึงเครื่องเล่นได้โดยใช้ Player.getApplicationLooper การรักษา Looper ที่แชร์ระหว่างเครื่องเล่นกับ PreloadManager จะช่วยให้มั่นใจได้ว่าการดำเนินการทั้งหมดในออบเจ็กต์สื่อที่แชร์เหล่านี้จะได้รับการจัดลำดับในคิวข้อความของเธรดเดียว ซึ่งจะช่วยลดข้อบกพร่องที่เกิดจากการทำงานพร้อมกัน
การโต้ตอบทั้งหมดระหว่าง PreloadManager กับเพลเยอร์ที่มีแหล่งที่มาของสื่อที่จะโหลดหรือโหลดล่วงหน้าต้องเกิดขึ้นในเธรดการเล่นเดียวกัน การแชร์ Looper เป็นสิ่งจำเป็นสำหรับความปลอดภัยของเทรด ดังนั้นเราจึงต้องแชร์ PlaybackLooper ระหว่าง PreloadManager กับเพลเยอร์
PreloadManager เตรียมออบเจ็กต์ MediaSource ที่มีสถานะในเบื้องหลัง เมื่อโค้ด UI เรียกใช้ player.setMediaSource(mediaSource) คุณจะส่งต่อออบเจ็กต์ที่มีสถานะและซับซ้อนนี้จาก MediaSource ที่โหลดล่วงหน้าไปยังเพลเยอร์ ในสถานการณ์นี้ ระบบจะย้าย PreloadMediaSource ทั้งหมดจากเครื่องมือจัดการไปยังเพลเยอร์ การโต้ตอบและการส่งต่อทั้งหมดนี้ควรเกิดขึ้นใน PlaybackLooper เดียวกัน
หาก PreloadManager และ ExoPlayer ทำงานในเธรดที่ต่างกัน อาจเกิดภาวะแข่งขันได้ เธรดของ PreloadManager อาจแก้ไขสถานะภายในของ MediaSource (เช่น เขียนข้อมูลใหม่ลงในบัฟเฟอร์) ในขณะที่เธรดของเพลเยอร์พยายามอ่านจาก MediaSource ซึ่งจะทำให้เกิดลักษณะการทำงานที่คาดเดาไม่ได้, IllegalStateException ที่แก้ไขข้อบกพร่องได้ยาก
preloadManagerBuilder.setPreloadLooper(playbackLooper)
มาดูกันว่าคุณจะแชร์คอมโพเนนต์ทั้งหมดข้างต้นระหว่าง ExoPlayer กับ DefaultPreloadManager ในการตั้งค่าได้อย่างไร
val preloadManagerBuilder =
DefaultPreloadManager.Builder(context, targetPreloadStatusControl)
// Optional - Share components between ExoPlayer and DefaultPreloadManager
preloadManagerBuilder
.setBandwidthMeter(customBandwidthMeter)
.setLoadControl(customLoadControl)
.setMediaSourceFactory(customMediaSourceFactory)
.setTrackSelectorFactory(customTrackSelectorFactory)
.setRenderersFactory(customRenderersFactory)
.setPreloadLooper(playbackLooper)
val preloadManager = val preloadManagerBuilder.build()เคล็ดลับ: หากใช้คอมโพเนนต์เริ่มต้นใน ExoPlayer เช่น DefaultLoadControl เป็นต้น คุณไม่จำเป็นต้องแชร์คอมโพเนนต์เหล่านั้นกับ DefaultPreloadManager อย่างชัดแจ้ง เมื่อสร้างอินสแตนซ์ ExoPlayer ผ่าน buildExoPlayer ของ DefaultPreloadManager.Builder ระบบจะอ้างอิงคอมโพเนนต์เหล่านี้โดยอัตโนมัติหากคุณใช้การติดตั้งใช้งานเริ่มต้นที่มีการกำหนดค่าเริ่มต้น แต่หากใช้คอมโพเนนต์ที่กำหนดเองหรือการกำหนดค่าที่กำหนดเอง คุณควรแจ้ง DefaultPreloadManager เกี่ยวกับคอมโพเนนต์หรือการกำหนดค่าเหล่านั้นอย่างชัดแจ้งผ่าน API ด้านบน
การโหลดล่วงหน้าพร้อมใช้งานจริง: รูปแบบหน้าต่างแบบเลื่อน
ในฟีดแบบไดนามิก ผู้ใช้จะเลื่อนดูเนื้อหาได้แทบไม่จำกัด หากเพิ่มวิดีโอลงใน DefaultPreloadManager อย่างต่อเนื่องโดยไม่มีกลยุทธ์การนำออกที่สอดคล้องกัน คุณจะทำให้เกิด OutOfMemoryError อย่างหลีกเลี่ยงไม่ได้ MediaSource ที่โหลดล่วงหน้าแต่ละรายการจะเก็บ SampleQueue ซึ่งจัดสรรบัฟเฟอร์หน่วยความจำ เมื่อมีจำนวนมากขึ้นเรื่อยๆ ก็อาจทำให้พื้นที่ฮีปของแอปพลิเคชันเต็ม โซลูชันนี้คืออัลกอริทึมที่คุณอาจคุ้นเคยอยู่แล้ว ซึ่งเรียกว่าหน้าต่างเลื่อน รูปแบบหน้าต่างเลื่อนจะเก็บชุดรายการขนาดเล็กที่จัดการได้ไว้ในหน่วยความจำ ซึ่งอยู่ติดกับตำแหน่งปัจจุบันของผู้ใช้ในฟีด ขณะที่ผู้ใช้เลื่อน "หน้าต่าง" ของรายการที่จัดการนี้จะเลื่อนตามไปด้วย โดยจะเพิ่มรายการใหม่ที่เข้ามาในมุมมอง และนำรายการที่อยู่ไกลออก
การใช้รูปแบบหน้าต่างเลื่อน
คุณควรทราบว่า PreloadManager ไม่มีเมธอด setWindowSize() ในตัว กรอบเวลาแบบเลื่อนเป็นรูปแบบการออกแบบที่คุณในฐานะนักพัฒนาแอปมีหน้าที่รับผิดชอบในการติดตั้งใช้งานโดยใช้เมธอด add() และ remove() แบบดั้งเดิม ตรรกะของแอปพลิเคชันต้องเชื่อมต่อเหตุการณ์ UI เช่น การเลื่อนหรือการเปลี่ยนหน้า กับการเรียก API เหล่านี้ หากต้องการดูข้อมูลอ้างอิงโค้ดสำหรับเรื่องนี้ เรามีรูปแบบหน้าต่างเลื่อนที่ใช้ในตัวอย่าง socialite ซึ่งมี PreloadManagerWrapper ที่เลียนแบบหน้าต่างเลื่อนด้วย
อย่าลืมเพิ่ม preloadManager.remove(mediaItem) ในการติดตั้งใช้งานเมื่อรายการไม่น่าจะปรากฏในการดูของผู้ใช้ในเร็วๆ นี้ การไม่นำรายการที่ไม่ได้อยู่ใกล้กับผู้ใช้แล้วออกเป็นสาเหตุหลักของปัญหาเกี่ยวกับหน่วยความจำในการติดตั้งใช้งานการโหลดล่วงหน้า การเรียกใช้ remove() จะช่วยให้มั่นใจได้ว่าระบบจะปล่อยทรัพยากรที่ช่วยให้คุณควบคุมการใช้งานหน่วยความจำของแอปและทำให้แอปเสถียร
การปรับแต่งกลยุทธ์การโหลดล่วงหน้าที่จัดหมวดหมู่ด้วย TargetPreloadStatusControl
ตอนนี้เราได้กำหนดแล้วว่าจะโหลดอะไรล่วงหน้า (รายการในหน้าต่าง) เราจึงสามารถใช้กลยุทธ์ที่กำหนดไว้อย่างดีสำหรับจำนวนที่จะโหลดล่วงหน้าสำหรับแต่ละรายการ เราได้เห็นวิธีบรรลุความละเอียดระดับนี้ด้วยการตั้งค่า TargetPreloadStatusControl ในส่วนที่ 1 แล้ว
โปรดทราบว่ารายการที่ตำแหน่ง +/- 1 อาจมีโอกาสเล่นสูงกว่ารายการที่ตำแหน่ง +/- 4 คุณสามารถจัดสรรทรัพยากร (เครือข่าย, CPU, หน่วยความจำ) ให้กับรายการที่ผู้ใช้มีแนวโน้มจะดูมากที่สุดในลำดับถัดไป ซึ่งจะสร้างกลยุทธ์ "การโหลดล่วงหน้า" ตามความใกล้เคียง ซึ่งเป็นกุญแจสำคัญในการปรับสมดุลการเล่นทันทีกับการใช้ทรัพยากรอย่างมีประสิทธิภาพ
คุณสามารถใช้ข้อมูลวิเคราะห์ผ่าน PreloadManagerListener ตามที่อธิบายไว้ในส่วนก่อนหน้าเพื่อกำหนดกลยุทธ์ระยะเวลาการโหลดล่วงหน้า
บทสรุปและขั้นตอนถัดไป
ตอนนี้คุณมีความรู้ขั้นสูงในการสร้างฟีดสื่อที่รวดเร็ว เสถียร และประหยัดทรัพยากรโดยใช้ DefaultPreloadManager ของ Media3 แล้ว
มาสรุปประเด็นสำคัญกัน
- ใช้ PreloadManagerListener เพื่อรวบรวมข้อมูลเชิงลึกด้านการวิเคราะห์และใช้การจัดการข้อผิดพลาดที่มีประสิทธิภาพ
- ใช้ DefaultPreloadManager.Builder รายการเดียวเสมอเพื่อสร้างทั้งอินสแตนซ์ของตัวจัดการและเพลเยอร์ เพื่อให้มั่นใจว่าคอมโพเนนต์ที่สำคัญจะได้รับการแชร์
- ใช้รูปแบบหน้าต่างเลื่อนโดยจัดการการเรียก add() และ remove() อย่างแข็งขันเพื่อป้องกัน OutOfMemoryError
- ใช้ TargetPreloadStatusControl เพื่อสร้างกลยุทธ์การโหลดล่วงหน้าแบบหลายระดับที่ชาญฉลาด ซึ่งจะช่วยปรับสมดุลประสิทธิภาพและการใช้ทรัพยากร
ตอนที่ 3: การแคชด้วยสื่อที่โหลดล่วงหน้า
การโหลดข้อมูลล่วงหน้าลงในหน่วยความจำจะช่วยเพิ่มประสิทธิภาพได้ทันที แต่ก็อาจมีข้อเสีย เมื่อปิดแอปพลิเคชันหรือนำสื่อที่โหลดล่วงหน้าออกจากตัวจัดการแล้ว ข้อมูลจะหายไป หากต้องการเพิ่มประสิทธิภาพในระดับที่สม่ำเสมอมากขึ้น เราสามารถรวมการโหลดล่วงหน้ากับการแคชในดิสก์ได้ ฟีเจอร์นี้อยู่ระหว่างการพัฒนาและจะพร้อมใช้งานในอีกไม่กี่เดือนข้างหน้า
คุณมีความคิดเห็นที่ต้องการแชร์ไหม เรายินดีรับฟังความคิดเห็นจากคุณ
โปรดติดตามข่าวสารและไปทำให้การเล่นวิดีโอเร็วขึ้นกันเลย 🚀
-
ข่าวสารเกี่ยวกับผลิตภัณฑ์ในแอปที่เน้นสื่อเป็นหลักในปัจจุบัน การมอบประสบการณ์การเล่นที่ราบรื่นและไม่ขาดตอนเป็นกุญแจสำคัญในการมอบประสบการณ์ที่น่าพึงพอใจแก่ผู้ใช้ ผู้ใช้คาดหวังว่าวิดีโอจะเริ่มเล่นทันทีและเล่นได้อย่างราบรื่นโดยไม่มีการหยุดชั่วคราว
Mayuri Khinvasara Khabya • อ่าน 8 นาที -
ข่าวสารเกี่ยวกับผลิตภัณฑ์ใน Google Play เราขยายแพลตฟอร์มการสมัครใช้บริการอย่างต่อเนื่องเพื่อช่วยให้คุณขับเคลื่อนการเติบโต ปรับตัวให้เข้ากับโมเดลธุรกิจใหม่ๆ และเข้าถึงผู้ใช้ได้ตรงจุด
Sheenam Mittal • อ่าน 4 นาที -
ข่าวสารเกี่ยวกับผลิตภัณฑ์เมื่อปีที่แล้ว Android Studio ได้เปิดให้ใช้โมเดล AI ใดก็ได้ วันนี้เราจะก้าวไปอีกขั้นด้วยการเปิดตัวการรองรับเอเจนต์การเขียนโค้ดที่คุณเลือก
Matthew Warner • ใช้เวลาอ่าน 3 นาที
รับข้อมูลเชิงลึกด้านการพัฒนา Android ล่าสุดส่งตรงถึงกล่องจดหมายของคุณทุกสัปดาห์