ข่าวสารผลิตภัณฑ์
ยกระดับการเล่นสื่อ: เจาะลึก 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): การเรียกกลับนี้จะเรียกใช้เมื่อคำขอโหลดล่วงหน้าเสร็จสมบูรณ์ตามที่กำหนดโดย TargetPreloadStatusControl
- onError(PreloadException error): การเรียกกลับนี้อาจมีประโยชน์สำหรับการแก้ไขข้อบกพร่องและการตรวจสอบ โดยจะเรียกใช้เมื่อการโหลดล่วงหน้าล้มเหลวและแสดงข้อยกเว้นที่เกี่ยวข้อง
คุณสามารถลงทะเบียน 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)
การดึงข้อมูลเชิงลึกจาก Listener
คุณสามารถเชื่อมต่อการเรียกกลับของ Listener เหล่านี้กับไปป์ไลน์ข้อมูลวิเคราะห์ การส่งต่อเหตุการณ์เหล่านี้ไปยังเครื่องมือข้อมูลวิเคราะห์จะช่วยให้คุณตอบคำถามสำคัญๆ ได้ เช่น
- อัตราความสำเร็จในการโหลดล่วงหน้าของเราคือเท่าใด (อัตราส่วนของเหตุการณ์ onCompleted ต่อจำนวนครั้งทั้งหมดที่พยายามโหลดล่วงหน้า)
- CDN หรือรูปแบบวิดีโอใดมีอัตราข้อผิดพลาดสูงสุด (โดยการแยกวิเคราะห์ข้อยกเว้นจาก onError)
- อัตราข้อผิดพลาดในการโหลดล่วงหน้าของเราคือเท่าใด (อัตราส่วนของเหตุการณ์ onError ต่อจำนวนครั้งทั้งหมดที่พยายามโหลดล่วงหน้า)
ข้อมูลนี้จะให้ความคิดเห็นเชิงปริมาณเกี่ยวกับกลยุทธ์การโหลดล่วงหน้า ซึ่งช่วยให้คุณทำการทดสอบ A/B และปรับปรุงประสบการณ์ของผู้ใช้โดยอิงตามข้อมูลได้ นอกจากนี้ ข้อมูลนี้ยังช่วยให้คุณปรับระยะเวลาการโหลดล่วงหน้า และจำนวนวิดีโอที่ต้องการโหลดล่วงหน้า รวมถึงบัฟเฟอร์ที่จัดสรรได้อย่างชาญฉลาด
มากกว่าการแก้ไขข้อบกพร่อง: การใช้ onError สำหรับการสำรอง UI อย่างราบรื่น
การโหลดล่วงหน้าล้มเหลวเป็นตัวบ่งชี้ที่ชัดเจนว่าผู้ใช้จะพบเหตุการณ์การบัฟเฟอร์ในเร็วๆ นี้ การเรียกกลับ onError ช่วยให้คุณตอบสนองได้อย่างรวดเร็ว แทนที่จะเพียงบันทึกข้อผิดพลาด คุณสามารถปรับ 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 เลือกแทร็กที่มีคุณภาพสูงสุดได้ตามสภาพเครือข่ายปัจจุบันและสถานะของบัฟเฟอร์ระหว่างการโหลดล่วงหน้าหรือการเล่น จากนั้น 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 กับเพลเยอร์ แต่ควรใช้ TrackSelector อินสแตนซ์แต่มีการใช้งานเหมือนกัน ที่แตกต่างกัน เราจึงตั้งค่า TrackSelectorFactory แทน TrackSelector ใน DefaultPreloadManager.Builder
preloadManagerBuilder.setTrackSelectorFactory(customTrackSelectorFactory)
- Renderer: คอมโพเนนต์นี้มีหน้าที่ทำความเข้าใจความสามารถของเพลเยอร์โดยไม่ต้องสร้าง Renderer แบบเต็ม โดยจะตรวจสอบพิมพ์เขียวนี้เพื่อดูว่าเพลเยอร์สุดท้ายจะรองรับรูปแบบวิดีโอ เสียง และข้อความใดบ้าง ซึ่งช่วยให้คอมโพเนนต์เลือกและดาวน์โหลดแทร็กสื่อที่เข้ากันได้เท่านั้นได้อย่างชาญฉลาด และป้องกันการสิ้นเปลืองแบนด์วิดท์กับเนื้อหาที่เพลเยอร์เล่นไม่ได้
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 นาที
-
ข่าวสารผลิตภัณฑ์
Android กำลังเปลี่ยนจากระบบปฏิบัติการไปเป็นระบบอัจฉริยะ ซึ่งจะสร้างโอกาสในการมีส่วนร่วมกับแอปของคุณมากขึ้น โดยมีการประกาศเรื่องนี้ในวันนี้ระหว่าง The Android Show
Matthew McCullough • ใช้เวลาอ่าน 4 นาที
-
ข่าวสารผลิตภัณฑ์
ระบบนิเวศมือถือมีการพัฒนาอยู่เสมอ ซึ่งนำมาซึ่งโอกาสใหม่ๆ และภัยคุกคามใหม่ๆ Android และ Google Play ยังคงมุ่งมั่นที่จะดูแลให้ผู้ใช้หลายพันล้านคนสามารถเพลิดเพลินกับแอปได้อย่างมั่นใจ และนักพัฒนาแอปสามารถสร้างสรรค์นวัตกรรมได้อย่างเต็มที่
Vijaya Kaza • ใช้เวลาอ่าน 3 นาที
รับข่าวสาร
รับข้อมูลเชิงลึกด้านการพัฒนา Android ล่าสุดส่งตรงถึงกล่องจดหมายของคุณ ทุกสัปดาห์