fix memleaks

This commit is contained in:
Felix 2020-04-08 00:55:26 +02:00
parent 3f3bb6cb9b
commit e698bdc870
14 changed files with 68 additions and 54 deletions

View file

@ -31,6 +31,7 @@
<activity
android:name=".settings.ChaosflixSettingsActivity"
android:theme="@style/ChaosflixLeanbackPreferences" />
</application>
<uses-feature

View file

@ -5,8 +5,6 @@ import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.leanback.app.ErrorSupportFragment
class BrowseErrorFragment : ErrorSupportFragment() {
@ -78,6 +76,11 @@ class BrowseErrorFragment : ErrorSupportFragment() {
}
}
override fun onDestroyView() {
super.onDestroyView()
spinnerFragment = null
}
companion object {
private val TRANSLUCENT = true

View file

@ -8,6 +8,7 @@ import androidx.leanback.widget.OnItemViewClickedListener
import androidx.leanback.widget.Presenter
import androidx.leanback.widget.Row
import androidx.leanback.widget.RowPresenter
import de.nicidienase.chaosflix.LeakCanaryLauncher
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Conference
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event
import de.nicidienase.chaosflix.common.mediadata.entities.streaming.Room

View file

@ -2,6 +2,7 @@ package de.nicidienase.chaosflix.leanback.conferences
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.leanback.app.BrowseSupportFragment
import androidx.leanback.widget.ArrayObjectAdapter
import androidx.leanback.widget.DividerRow
@ -20,6 +21,7 @@ import de.nicidienase.chaosflix.common.util.ConferenceUtil
import de.nicidienase.chaosflix.common.viewmodel.BrowseViewModel
import de.nicidienase.chaosflix.common.viewmodel.ViewModelFactory
import de.nicidienase.chaosflix.leanback.BrowseErrorFragment
import de.nicidienase.chaosflix.leanback.BuildConfig
import de.nicidienase.chaosflix.leanback.CardPresenter
import de.nicidienase.chaosflix.leanback.ChaosflixEventAdapter
import de.nicidienase.chaosflix.leanback.DiffCallbacks
@ -57,8 +59,9 @@ class ConferencesBrowseFragment : BrowseSupportFragment() {
Conferences
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
title = resources.getString(R.string.app_name)
badgeDrawable = resources.getDrawable(R.drawable.chaosflix_icon, null)
@ -87,10 +90,13 @@ class ConferencesBrowseFragment : BrowseSupportFragment() {
val listRowAdapter = ArrayObjectAdapter(settingsPresenter)
listRowAdapter.add(SelectableContentItem.Settings)
listRowAdapter.add(SelectableContentItem.About)
if(BuildConfig.DEBUG){
listRowAdapter.add(SelectableContentItem.LeakCanary)
}
settingsRow = ListRow(HeaderItem("Chaosflix"), listRowAdapter)
rowsAdapter.add(0, settingsRow)
viewModel.getConferenceGroups().observe(this, Observer { conferenceGroups ->
viewModel.getConferenceGroups().observe(viewLifecycleOwner, Observer { conferenceGroups ->
if (conferenceGroups != null && conferenceGroups.isNotEmpty()) {
val conferenceRows = ArrayList<Row>()
errorFragment?.dismiss(fragmentManager)
@ -108,7 +114,7 @@ class ConferencesBrowseFragment : BrowseSupportFragment() {
}
})
viewModel.getUpdateState().observe(this, Observer { downloaderEvent ->
viewModel.getUpdateState().observe(viewLifecycleOwner, Observer { downloaderEvent ->
when (downloaderEvent?.state) {
MediaRepository.State.RUNNING -> {
Log.i(TAG, "Refresh running")
@ -127,7 +133,7 @@ class ConferencesBrowseFragment : BrowseSupportFragment() {
}
})
viewModel.getBookmarkedEvents().observe(this, Observer { bookmarks ->
viewModel.getBookmarkedEvents().observe(viewLifecycleOwner, Observer { bookmarks ->
if (bookmarks != null) {
watchListAdapter.setItems(bookmarks, DiffCallbacks.eventDiffCallback)
watchListAdapter.notifyItemRangeChanged(0, bookmarks.size)
@ -136,7 +142,7 @@ class ConferencesBrowseFragment : BrowseSupportFragment() {
}
}
})
viewModel.getInProgressEvents().observe(this, Observer { inProgress ->
viewModel.getInProgressEvents().observe(viewLifecycleOwner, Observer { inProgress ->
if (inProgress != null) {
inProgressAdapter.setItems(inProgress, DiffCallbacks.eventDiffCallback)
inProgressAdapter.notifyItemRangeChanged(0, inProgress.size)
@ -146,7 +152,7 @@ class ConferencesBrowseFragment : BrowseSupportFragment() {
}
})
viewModel.getPromotedEvents().observe(this, Observer { promoted ->
viewModel.getPromotedEvents().observe(viewLifecycleOwner, Observer { promoted ->
if (promoted != null) {
promotedAdapter.setItems(promoted, DiffCallbacks.eventDiffCallback)
promotedAdapter.notifyItemRangeChanged(0, promoted.size)
@ -156,7 +162,7 @@ class ConferencesBrowseFragment : BrowseSupportFragment() {
}
})
viewModel.getLivestreams().observe(this, Observer { liveConferences ->
viewModel.getLivestreams().observe(viewLifecycleOwner, Observer { liveConferences ->
if (liveConferences != null && liveConferences.isNotEmpty()) {
val streamRows = buildStreamRows(eventPresenter, liveConferences)
updateStreams(streamRows)
@ -164,6 +170,11 @@ class ConferencesBrowseFragment : BrowseSupportFragment() {
})
}
override fun onDestroyView() {
super.onDestroyView()
errorFragment = null
}
private fun updateSectionRecomendations() =
updateSection(
Section.Recommendations,
@ -275,7 +286,7 @@ class ConferencesBrowseFragment : BrowseSupportFragment() {
}
private fun bindConferencesToRow(group: ConferenceGroup, row: ListRow) {
viewModel.getConferencesByGroup(group.id).observe(this, Observer { conferences ->
viewModel.getConferencesByGroup(group.id).observe(viewLifecycleOwner, Observer { conferences ->
(row.adapter as ArrayObjectAdapter).setItems(conferences?.sorted(), DiffCallbacks.conferenceDiffCallback)
})
}

View file

@ -221,7 +221,7 @@ class EventDetailsFragment : DetailsSupportFragment() {
actionAdapter.add(watchlistAction)
event.guid.let {
loadPlaybackProgress(it)
detailsViewModel.getBookmarkForEvent(it).observe(this, Observer { watchlistItem ->
detailsViewModel.getBookmarkForEvent(it).observe(viewLifecycleOwner, Observer { watchlistItem ->
if (watchlistItem != null) {
watchlistAction.id = ACTION_REMOVE_WATCHLIST
watchlistAction.label1 = getString(R.string.remove_from_watchlist)
@ -240,7 +240,7 @@ class EventDetailsFragment : DetailsSupportFragment() {
initializeBackgroundWithImage(event.posterUrl)
detailsViewModel.getRelatedEvents(event).observe(this, Observer { events ->
detailsViewModel.getRelatedEvents(event).observe(viewLifecycleOwner, Observer { events ->
if (relatedEventsAdapter == null) {
relatedEventsAdapter = ArrayObjectAdapter(CardPresenter(R.style.EventCardStyle))
val header = HeaderItem(getString(R.string.related_talks))

View file

@ -7,6 +7,7 @@ import android.util.Log
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import de.nicidienase.chaosflix.common.ChaosflixUtil
import de.nicidienase.chaosflix.common.mediadata.MediaRepository
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Conference
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Event
@ -60,9 +61,7 @@ class EventsActivity : androidx.fragment.app.FragmentActivity() {
viewModel.getEventsforConference(conference).observe(this, Observer { events ->
events?.let {
if (it.isNotEmpty()) {
val tagList = events.map { it.tags ?: emptyArray() }.toTypedArray().flatten()
val filteredTags = tagList.filterNot { it.matches("\\d+".toRegex()) }.filterNot { it == conference.acronym }.toSet()
updateFragment(filteredTags.size > 1)
updateFragment(ChaosflixUtil.areTagsUsefull(events, conference.acronym))
(fragment as EventsFragment).updateEvents(conference, it)
}
}

View file

@ -3,17 +3,16 @@ package de.nicidienase.chaosflix.touch.browse;
import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import de.nicidienase.chaosflix.touch.R;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.ConferenceGroup;
import de.nicidienase.chaosflix.touch.R;
import de.nicidienase.chaosflix.touch.browse.adapters.ConferenceRecyclerViewAdapter;
public class ConferenceGroupFragment extends BrowseFragment {
@ -71,7 +70,7 @@ public class ConferenceGroupFragment extends BrowseFragment {
conferencesAdapter = new ConferenceRecyclerViewAdapter(listener);
conferencesAdapter.setHasStableIds(true);
recyclerView.setAdapter(conferencesAdapter);
getViewModel().getConferencesByGroup(conferenceGroup.getId()).observe(this, conferenceList -> {
getViewModel().getConferencesByGroup(conferenceGroup.getId()).observe(getViewLifecycleOwner(), conferenceList -> {
if(conferenceList != null){
if(conferenceList.size() > 0){
setLoadingOverlayVisibility(false);

View file

@ -2,16 +2,17 @@ package de.nicidienase.chaosflix.touch.browse;
import android.content.Context;
import android.os.Bundle;
import com.google.android.material.snackbar.Snackbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.android.material.snackbar.Snackbar;
import de.nicidienase.chaosflix.R;
import de.nicidienase.chaosflix.common.mediadata.entities.recording.persistence.Conference;
import de.nicidienase.chaosflix.touch.databinding.FragmentTabPagerLayoutBinding;
import de.nicidienase.chaosflix.touch.browse.adapters.ConferenceGroupsFragmentPager;
import de.nicidienase.chaosflix.touch.databinding.FragmentTabPagerLayoutBinding;
public class ConferencesTabBrowseFragment extends BrowseFragment {
@ -61,7 +62,7 @@ public class ConferencesTabBrowseFragment extends BrowseFragment {
setupToolbar(binding.incToolbar.toolbar, R.string.app_name);
setOverlay(binding.incOverlay.loadingOverlay);
getViewModel().getConferenceGroups().observe(this, conferenceGroups -> {
getViewModel().getConferenceGroups().observe(getViewLifecycleOwner(), conferenceGroups -> {
if(conferenceGroups.size() > 0){
this.setLoadingOverlayVisibility(false);
}
@ -75,7 +76,7 @@ public class ConferencesTabBrowseFragment extends BrowseFragment {
setLoadingOverlayVisibility(false);
}
});
getViewModel().getUpdateState().observe(this, state -> {
getViewModel().getUpdateState().observe(getViewLifecycleOwner(), state -> {
if(state == null){
return;
}

View file

@ -37,7 +37,7 @@ class DownloadsListFragment : BrowseFragment() {
list.layoutManager =
StaggeredGridLayoutManager(columnCount - 1, StaggeredGridLayoutManager.VERTICAL)
}
viewModel.getOfflineDisplayEvents().observe(this@DownloadsListFragment, Observer {
viewModel.getOfflineDisplayEvents().observe(viewLifecycleOwner, Observer {
if (it != null) {
offlineEventAdapter.items = it
}

View file

@ -118,21 +118,21 @@ public class EventsListFragment extends BrowseFragment implements SearchView.OnQ
if (type == TYPE_BOOKMARKS) {
setupToolbar(binding.incToolbar.toolbar, R.string.bookmarks);
eventAdapter.setShowConferenceName(true);
getViewModel().getBookmarkedEvents().observe(this, listObserver);
getViewModel().getBookmarkedEvents().observe(getViewLifecycleOwner(), listObserver);
} else if (type == TYPE_IN_PROGRESS) {
setupToolbar(binding.incToolbar.toolbar, R.string.continue_watching);
eventAdapter.setShowConferenceName(true);
getViewModel().getInProgressEvents().observe(this, listObserver);
getViewModel().getInProgressEvents().observe(getViewLifecycleOwner(), listObserver);
} else if (type == TYPE_EVENTS) {
{
setupToolbar(binding.incToolbar.toolbar, conference.getTitle(), false);
getViewModel().getEventsforConference(conference).observe(this, events -> {
getViewModel().getEventsforConference(conference).observe(getViewLifecycleOwner(), events -> {
if (events != null) {
setEvents(events);
setLoadingOverlayVisibility(false);
}
});
getViewModel().updateEventsForConference(conference).observe(this, state -> {
getViewModel().updateEventsForConference(conference).observe(getViewLifecycleOwner(), state -> {
MediaRepository.State downloaderState = state.getState();
switch (downloaderState) {
case RUNNING:

View file

@ -69,7 +69,7 @@ class LivestreamListFragment : BrowseFragment() {
// }, 500)
binding.swipeRefreshLayout.isRefreshing = true
Log.d(TAG, "Refresh starting")
viewModel.getLivestreams().observe(this, Observer {
viewModel.getLivestreams().observe(viewLifecycleOwner, Observer {
it?.let { adapter.setContent(it) }
binding.swipeRefreshLayout.isRefreshing = false
if (it?.size == 0 && !snackbar.isShown) {

View file

@ -105,7 +105,7 @@ class EventDetailsFragment : androidx.fragment.app.Fragment() {
.get(DetailsViewModel::class.java)
viewModel.setEvent(event)
.observe(this, Observer {
.observe(viewLifecycleOwner, Observer {
Log.d(TAG, "Loading Event ${event.title}, ${event.guid}")
updateBookmark(event.guid)
binding.thumbImage.transitionName = getString(R.string.thumbnail) + event.guid
@ -115,7 +115,7 @@ class EventDetailsFragment : androidx.fragment.app.Fragment() {
.apply(RequestOptions().fitCenter())
.into(binding.thumbImage)
})
viewModel.getRelatedEvents(event).observe(this, Observer {
viewModel.getRelatedEvents(event).observe(viewLifecycleOwner, Observer {
if (it != null) {
relatedEventsAdapter.items = it
}
@ -131,7 +131,7 @@ class EventDetailsFragment : androidx.fragment.app.Fragment() {
private fun updateBookmark(guid: String) {
viewModel.getBookmarkForEvent(guid)
.observe(this, Observer { watchlistItem: WatchlistItem? ->
.observe(viewLifecycleOwner, Observer { watchlistItem: WatchlistItem? ->
this.watchlistItem = watchlistItem
listener?.invalidateOptionsMenu()
})
@ -164,7 +164,7 @@ class EventDetailsFragment : androidx.fragment.app.Fragment() {
menu.findItem(R.id.action_bookmark).isVisible = watchlistItem == null
menu.findItem(R.id.action_unbookmark).isVisible = watchlistItem != null
// menu.findItem(R.id.action_download).isVisible = viewModel.writeExternalStorageAllowed
// viewModel.offlineItemExists(event).observe(this, Observer { itemExists->
// viewModel.offlineItemExists(event).observe(viewLifecycleOwner, Observer { itemExists->
// itemExists?.let {exists ->
// menu.findItem(R.id.action_download).isVisible =
// viewModel.writeExternalStorageAllowed && !exists
@ -208,7 +208,7 @@ class EventDetailsFragment : androidx.fragment.app.Fragment() {
return true
}
R.id.action_delete_offline_item -> {
viewModel.deleteOfflineItem(event).observe(this, Observer { success ->
viewModel.deleteOfflineItem(event).observe(viewLifecycleOwner, Observer { success ->
if (success != null) {
view?.let { Snackbar.make(it, "Deleted Download", Snackbar.LENGTH_SHORT).show() }
}

View file

@ -1,18 +1,8 @@
package de.nicidienase.chaosflix.touch.playback;
import androidx.lifecycle.ViewModelProviders;
import androidx.databinding.DataBindingUtil;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.snackbar.Snackbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
@ -21,11 +11,19 @@ import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.ViewModelProviders;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.LoadControl;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
@ -44,11 +42,12 @@ import com.google.android.exoplayer2.upstream.DefaultHttpDataSource;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
import com.google.android.exoplayer2.upstream.HttpDataSource;
import com.google.android.exoplayer2.util.Util;
import com.google.android.material.snackbar.Snackbar;
import de.nicidienase.chaosflix.touch.R;
import de.nicidienase.chaosflix.common.viewmodel.PlayerViewModel;
import de.nicidienase.chaosflix.touch.databinding.FragmentExoPlayerBinding;
import de.nicidienase.chaosflix.common.viewmodel.ViewModelFactory;
import de.nicidienase.chaosflix.touch.R;
import de.nicidienase.chaosflix.touch.databinding.FragmentExoPlayerBinding;
public class ExoPlayerFragment extends Fragment implements PlayerEventListener.PlayerStateChangeListener {
private static final String TAG = ExoPlayerFragment.class.getSimpleName();
@ -145,7 +144,7 @@ public class ExoPlayerFragment extends Fragment implements PlayerEventListener.P
if (exoPlayer != null) {
exoPlayer.setPlayWhenReady(playbackState);
viewModel.getPlaybackProgressLiveData(item.getEventGuid()).observe(this, playbackProgress -> {
viewModel.getPlaybackProgressLiveData(item.getEventGuid()).observe(getViewLifecycleOwner(), playbackProgress -> {
if (playbackProgress != null) {
exoPlayer.seekTo(playbackProgress.getProgress());
}

View file

@ -142,7 +142,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
private fun importFavorites() {
var snackbar: Snackbar? = null
viewModel.importFavorites().observe(this, Observer { event ->
viewModel.importFavorites().observe(viewLifecycleOwner, Observer { event ->
when {
event?.state == PreferencesViewModel.State.Loading -> {
snackbar?.dismiss()