【Android 性能优化:内存篇】——ExoPlayer 释放后内存没有恢复问题探索

本文主要是介绍【Android 性能优化:内存篇】——ExoPlayer 释放后内存没有恢复问题探索,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景

最近笔者承接项目的内存优化指标,在内存调研的过程中发现项目中视频播放结束后,内存没有恢复到播放前到水平。项目中用的 EXO 版本为2.19.1,并且笔者自己也写了个简单的 Demo,发现也是如此。虽然有一些偏门方法可以优化,但是暂时还是未能正面突破,各位看官,如果有什么idea,欢迎留言多多指教~

分析

笔者的 Demo 如下

 api 'com.google.android.exoplayer:exoplayer:2.19.1'

VideoTestFragment.java 

package com.mikel.projectdemo.uiframework;import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.ui.PlayerView;
import com.mikel.projectdemo.R;
import org.jetbrains.annotations.NotNull;public class VideoTestFragment extends Fragment {public static VideoTestFragment build() {return new VideoTestFragment();}private Context mContext;private SimpleExoPlayer mSimpleExoPlayer;private PlayerView playerView;@Overridepublic View onCreateView(@NonNull @NotNull LayoutInflater inflater, @Nullable @org.jetbrains.annotations.Nullable ViewGroup container, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {mContext = getActivity();View rootView = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_video_item, null, true);initUI(rootView);return rootView;}private void initUI(View rootView) {mSimpleExoPlayer = new SimpleExoPlayer.Builder(getActivity()).build();// 准备要播放的媒体资源MediaItem mediaItem = MediaItem.fromUri("https://vfx.mtime.cn/Video/2019/01/15/mp4/190115161611510728_480.mp4");mSimpleExoPlayer.setMediaItem(mediaItem);// 将ExoPlayer关联到要显示视频的ViewplayerView = rootView.findViewById(R.id.player_view);playerView.setPlayer(mSimpleExoPlayer);}public void startPlay() {// 准备播放器mSimpleExoPlayer.prepare();mSimpleExoPlayer.play();}/*** 停止播放*/public void stopPlay() {pausePlay();if(mSimpleExoPlayer != null) {mSimpleExoPlayer.release();mSimpleExoPlayer = null;}}public void resumePlay() {if(mSimpleExoPlayer != null) {mSimpleExoPlayer.setPlayWhenReady(true);} else {startPlay();}}public void pausePlay() {if(mSimpleExoPlayer != null) {mSimpleExoPlayer.setPlayWhenReady(false);}}@Overridepublic void onDestroyView() {super.onDestroyView();stopPlay();}@Overridepublic void onResume() {super.onResume();resumePlay();}@Overridepublic void onStop() {super.onStop();pausePlay();}
}

 fragment_video_item.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><com.google.android.exoplayer2.ui.PlayerViewandroid:id="@+id/player_view"android:layout_width="match_parent"android:layout_height="match_parent"></com.google.android.exoplayer2.ui.PlayerView>
</FrameLayout>

VideoTestActivity.java

public class VideoTestActivity extends AppCompatActivity {public static void startActivity(Context context) {Intent intent = new Intent(context, VideoTestActivity.class);context.startActivity(intent);}@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_video_test);FragmentManager fragmentManager = getSupportFragmentManager();VideoTestFragment videoTestFragment = VideoTestFragment.build();FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();fragmentTransaction.add(R.id.fragment_container, videoTestFragment);fragmentTransaction.commit();}
}

activity_video_test.xml 

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><FrameLayoutandroid:id="@+id/fragment_container"android:layout_width="match_parent"android:layout_height="match_parent"></FrameLayout>
</FrameLayout>

 打开播放页面前和播放后关闭页面,内存水位如下:

内存水位简直毫无波澜,笔者也在 ExoPlayer 上发现不少相关 Issue:

https://github.com/google/ExoPlayer/issues/9755

 Memory leak · Issue #1855 · google/ExoPlayer · GitHub

issue 里有一个方法是说在页面onDestroy的时候不仅释放Exoplayer, 还需要加上 simpleExoPlayerView.setPlayer(null),并且把 simpleExoPlayerView也设置为空,笔者尝试了下,内存水位依旧没有太大变化

解决方案探索

方案1 独立进程

业务允许的情况下,把播放页面设置成独立进程,

        <activity android:name=".video.VideoTestActivity"android:process=":video">

退出页面后调用

android.os.Process.killProcess(android.os.Process.myPid());

 该方案适合播放场景单一,使用Activity 来承接视频播放,播放结束后少频繁进入播放页面

方案 2 主动触发 gc

如果业务限制,无法把播放页面放到独立进程,尝试下 VideoFragment onDestroy 的时候主动 Runtime.getRuntime().gc()

该方案剑走偏峰,也是适合播放场景单一,不是频繁打开播放页面的场景,否则频繁手动 gc 可能带来卡顿的性能问题。

各位看官,如果对 ExoPlayer 研究深入或者有什么idea,欢迎留言多多指教~

这篇关于【Android 性能优化:内存篇】——ExoPlayer 释放后内存没有恢复问题探索的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/742439

相关文章

Vue3绑定props默认值问题

《Vue3绑定props默认值问题》使用Vue3的defineProps配合TypeScript的interface定义props类型,并通过withDefaults设置默认值,使组件能安全访问传入的... 目录前言步骤步骤1:使用 defineProps 定义 Props步骤2:设置默认值总结前言使用T

Web服务器-Nginx-高并发问题

《Web服务器-Nginx-高并发问题》Nginx通过事件驱动、I/O多路复用和异步非阻塞技术高效处理高并发,结合动静分离和限流策略,提升性能与稳定性... 目录前言一、架构1. 原生多进程架构2. 事件驱动模型3. IO多路复用4. 异步非阻塞 I/O5. Nginx高并发配置实战二、动静分离1. 职责2

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

解决升级JDK报错:module java.base does not“opens java.lang.reflect“to unnamed module问题

《解决升级JDK报错:modulejava.basedoesnot“opensjava.lang.reflect“tounnamedmodule问题》SpringBoot启动错误源于Jav... 目录问题描述原因分析解决方案总结问题描述启动sprintboot时报以下错误原因分析编程异js常是由Ja

Android协程高级用法大全

《Android协程高级用法大全》这篇文章给大家介绍Android协程高级用法大全,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习吧... 目录1️⃣ 协程作用域(CoroutineScope)与生命周期绑定Activity/Fragment 中手

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Java实现复杂查询优化的7个技巧小结

《Java实现复杂查询优化的7个技巧小结》在Java项目中,复杂查询是开发者面临的“硬骨头”,本文将通过7个实战技巧,结合代码示例和性能对比,手把手教你如何让复杂查询变得优雅,大家可以根据需求进行选择... 目录一、复杂查询的痛点:为何你的代码“又臭又长”1.1冗余变量与中间状态1.2重复查询与性能陷阱1.

Python内存优化的实战技巧分享

《Python内存优化的实战技巧分享》Python作为一门解释型语言,虽然在开发效率上有着显著优势,但在执行效率方面往往被诟病,然而,通过合理的内存优化策略,我们可以让Python程序的运行速度提升3... 目录前言python内存管理机制引用计数机制垃圾回收机制内存泄漏的常见原因1. 循环引用2. 全局变