赞
踩
最近笔者承接项目的内存优化指标,在内存调研的过程中发现项目中视频播放结束后,内存没有恢复到播放前到水平。项目中用的 EXO 版本为2.19.1,并且笔者自己也写了个简单的 Demo,发现也是如此。虽然有一些偏门方法可以优化,但是暂时还是未能正面突破,各位看官,如果有什么idea,欢迎留言多多指教~
笔者的 Demo 如下
api 'com.google.android.exoplayer:exoplayer:2.19.1'
- 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;
-
- @Override
- public 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关联到要显示视频的View
- playerView = 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);
- }
- }
-
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- stopPlay();
- }
-
- @Override
- public void onResume() {
- super.onResume();
- resumePlay();
- }
-
- @Override
- public void onStop() {
- super.onStop();
- pausePlay();
- }
- }

- <?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.PlayerView
- android:id="@+id/player_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- </com.google.android.exoplayer2.ui.PlayerView>
- </FrameLayout>
- public class VideoTestActivity extends AppCompatActivity {
-
- public static void startActivity(Context context) {
- Intent intent = new Intent(context, VideoTestActivity.class);
- context.startActivity(intent);
- }
-
- @Override
- protected 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();
-
- }
- }

- <?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">
-
- <FrameLayout
- android: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
android - ExoPlayer occupying memory even after releasing - Stack Overflow
issue 里有一个方法是说在页面onDestroy的时候不仅释放Exoplayer, 还需要加上 simpleExoPlayerView.setPlayer(null),并且把 simpleExoPlayerView也设置为空,笔者尝试了下,内存水位依旧没有太大变化。
业务允许的情况下,把播放页面设置成独立进程,
- <activity android:name=".video.VideoTestActivity"
- android:process=":video">
退出页面后调用
android.os.Process.killProcess(android.os.Process.myPid());
该方案适合播放场景单一,使用Activity 来承接视频播放,播放结束后少频繁进入播放页面
如果业务限制,无法把播放页面放到独立进程,尝试下 VideoFragment onDestroy 的时候主动 Runtime.getRuntime().gc()
该方案剑走偏峰,也是适合播放场景单一,不是频繁打开播放页面的场景,否则频繁手动 gc 可能带来卡顿的性能问题。
各位看官,如果对 ExoPlayer 研究深入或者有什么idea,欢迎留言多多指教~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。