утечка памяти в компоненте ExoPlayer с учетом жизненного цикла (настраиваемое представление с учетом жизненного цикла) с рекламой VAST - PullRequest
0 голосов
/ 31 марта 2020

извините за мой плохой Engli sh, я хочу сделать пользовательский просмотр поверх Google \ ExoPlayer , который

  • можно повторно использовать просто в нескольких разделах одного и того же Фрагмент или действие.
  • имеет пользовательский интерфейс управления воспроизведением (воспроизведение, пауза, полноэкранный режим, скорость, селектор качества, регуляторы яркости, регуляторы громкости)
  • обрабатывает само миниатюру
  • Включить рекламную систему VAST.
  • с учетом жизненного цикла (обрабатывать сам жизненный цикл)

это наш код:

https://github.com/alaatv/android-alaatv-exoplayer/blob/master/java/com/alaatv/component/player/AlaaTV.java

когда мы хотим использовать его во фрагменте, xml код:

<androidx.cardview.widget.CardView
                    android:id="@+id/intro_video"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_marginTop="@dimen/margin_10dp"
                    android:layout_marginEnd="@dimen/margin_10dp"
                    android:layout_marginBottom="@dimen/margin_10dp"
                    android:padding="@dimen/margin_10dp"
                    app:cardCornerRadius="5dp"
                    app:cardElevation="@dimen/card_dimen"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@id/selectableInfo">

                    <androidx.constraintlayout.widget.ConstraintLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content">

                        <com.alaatv.component.player.AlaaTV
                            android:id="@+id/card_alaatv_player_intro_video"
                            android:layout_width="match_parent"
                            android:layout_height="200dp"
                            android:adjustViewBounds="true"
                            android:scaleType="fitXY"
                            android:minHeight="@dimen/player_height"
                            android:visibility="gone"
                            custom:product_introduction_video="true"
                            app:layout_constraintBottom_toBottomOf="parent"
                            app:layout_constraintEnd_toEndOf="parent"
                            app:layout_constraintStart_toStartOf="parent"
                            app:layout_constraintTop_toTopOf="parent"
                            />


                        <androidx.appcompat.widget.AppCompatImageView
                            android:id="@+id/card_alaatv_intro_video_ic"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_gravity="center_horizontal"
                            android:src="@drawable/ic_video"
                            app:layout_constraintBottom_toBottomOf="parent"
                            app:layout_constraintEnd_toEndOf="parent"
                            app:layout_constraintStart_toStartOf="parent"
                            app:layout_constraintTop_toTopOf="parent" />

                    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.cardview.widget.CardView>

и во фрагменте - java код:

....
    @Override
    public void onViewCreated( @NonNull View view, @Nullable Bundle savedInstanceState ) {
        super.onViewCreated(view, savedInstanceState);
        ....
        mBinding.cardAlaatvPlayerIntroVideo.observe(getViewLifecycleOwner().getLifecycle());
        mBinding.cardAlaatvPlayerIntroVideo.setVastUrl("https://alaatv.com/vast.xml");
        mBinding.cardAlaatvIntroVideoIc.setVisibility(View.GONE);
        mBinding.cardAlaatvPlayerIntroVideo.setVideoUrls(introVideoUrl, introVideoUrl, introVideoUrl);
        mBinding.cardAlaatvPlayerIntroVideo.setVisibility(View.VISIBLE);
        mBinding.cardAlaatvPlayerIntroVideo.setPoster(videoPosterLink);
        mBinding.cardAlaatvPlayerIntroVideo.invalidate();
    }
    @Override
    public void onDestroyView( ) {
        super.onDestroyView();
        mBinding = null;
    }
...

Жизненный цикл ручки игрока включен :

https://github.com/alaatv/android-alaatv-exoplayer/blob/master/java/com/alaatv/component/player/PlayerLifecycleAware.java

и

https://github.com/alaatv/android-alaatv-exoplayer/blob/master/java/com/alaatv/component/player/AlaaTV.java

автоматически.

все в порядке, но с пакетом утечек:

debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.2'

мы обнаруживаем эту утечку памяти в пользовательском представлении:

┬───
│ GC Root: System class
│
├─ leakcanary.internal.InternalLeakCanary class
│    Leaking: NO (MainActivity↓ is not leaking and a class is never leaking)
│    ↓ static InternalLeakCanary.resumedActivity
├─ ir.sanatisharif.android.konkur96.MainActivity instance
│    Leaking: NO (Activity#mDestroyed is false)
│    ↓ MainActivity.mLifecycleRegistry
│                   ~~~~~~~~~~~~~~~~~~
├─ androidx.lifecycle.LifecycleRegistry instance
│    Leaking: UNKNOWN
│    ↓ LifecycleRegistry.mObserverMap
│                        ~~~~~~~~~~~~
├─ androidx.arch.core.internal.FastSafeIterableMap instance
│    Leaking: UNKNOWN
│    ↓ FastSafeIterableMap.mHashMap
│                          ~~~~~~~~
├─ java.util.HashMap instance
│    Leaking: UNKNOWN
│    ↓ HashMap.table
│              ~~~~~
├─ java.util.HashMap$HashMapEntry[] array
│    Leaking: UNKNOWN
│    ↓ HashMap$HashMapEntry[].[1]
│                             ~~~
├─ java.util.HashMap$HashMapEntry instance
│    Leaking: UNKNOWN
│    ↓ HashMap$HashMapEntry.key
│                           ~~~
├─ androidx.lifecycle.LiveData$LifecycleBoundObserver instance
│    Leaking: UNKNOWN
│    ↓ LiveData$LifecycleBoundObserver.mObserver
│                                      ~~~~~~~~~
├─ com.alaatv.component.player.-$$Lambda$AlaaTV$V6y4fIh-unzLnzWBvjU7U4RChTc instance
│    Leaking: UNKNOWN
│    ↓ -$$Lambda$AlaaTV$V6y4fIh-unzLnzWBvjU7U4RChTc.f$0
│                                                   ~~~
├─ com.alaatv.component.player.AlaaTV instance
│    Leaking: YES (View detached and has parent)
│    mContext instance of ir.sanatisharif.android.konkur96.MainActivity with mDestroyed = false
│    View#mParent is set
│    View#mAttachInfo is null (view detached)
│    View.mID = R.id.card_alaatv_player
│    View.mWindowAttachCount = 1
│    ↓ AlaaTV.mParent
├─ androidx.constraintlayout.widget.ConstraintLayout instance
│    Leaking: YES (AlaaTV↑ is leaking and View detached and has parent)
│    mContext instance of ir.sanatisharif.android.konkur96.MainActivity with mDestroyed = false
│    View#mParent is set
│    View#mAttachInfo is null (view detached)
│    View.mWindowAttachCount = 1
│    ↓ ConstraintLayout.mParent
├─ androidx.core.widget.NestedScrollView instance
│    Leaking: YES (ConstraintLayout↑ is leaking and View detached and has parent)
│    mContext instance of ir.sanatisharif.android.konkur96.MainActivity with mDestroyed = false
│    View#mParent is set
│    View#mAttachInfo is null (view detached)
│    View.mID = R.id.scrollVideoPage
│    View.mWindowAttachCount = 1
│    ↓ NestedScrollView.mParent
├─ androidx.constraintlayout.widget.ConstraintLayout instance
│    Leaking: YES (NestedScrollView↑ is leaking and View detached and has parent)
│    mContext instance of ir.sanatisharif.android.konkur96.MainActivity with mDestroyed = false
│    View#mParent is set
│    View#mAttachInfo is null (view detached)
│    View.mID = R.id.constraint_video_content
│    View.mWindowAttachCount = 1
│    ↓ ConstraintLayout.mParent
╰→ androidx.coordinatorlayout.widget.CoordinatorLayout instance
      Leaking: YES (ObjectWatcher was watching this because ir.sanatisharif.android.konkur96.view.ContentFragment received Fragment#onDestroyView() callback (references to its views should be cleared to prevent leaks))
      key = 5ff17abe-c47c-4567-a607-9e336f5ce824
      watchDurationMillis = 11574
      retainedDurationMillis = 6573
      key = 72552b3e-4a67-489c-99b3-39d7428dc2aa
      mContext instance of ir.sanatisharif.android.konkur96.MainActivity with mDestroyed = false
      View#mParent is null
      View#mAttachInfo is null (view detached)
      View.mWindowAttachCount = 1

METADATA

Build.VERSION.SDK_INT: 23
Build.MANUFACTURER: samsung
LeakCanary version: 2.2
App process name: ir.sanatisharif.android.konkur96
Analysis duration: 66639 ms

, пожалуйста, помогите мне решить эту проблему.

...