-Fixed memory leak in playlist append dialog due to rogue flowables.

-Changed image loader memory cache to use limited LRU.
This commit is contained in:
John Zhen Mo 2018-01-29 20:42:52 -08:00
parent 6f9deea873
commit 62814f083e
2 changed files with 35 additions and 11 deletions

View File

@ -10,6 +10,8 @@ import android.content.Intent;
import android.os.Build; import android.os.Build;
import android.util.Log; import android.util.Log;
import com.nostra13.universalimageloader.cache.memory.impl.LRULimitedMemoryCache;
import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache;
import com.nostra13.universalimageloader.cache.memory.impl.WeakMemoryCache; import com.nostra13.universalimageloader.cache.memory.impl.WeakMemoryCache;
import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
@ -81,10 +83,7 @@ public class App extends Application {
initNotificationChannel(); initNotificationChannel();
// Initialize image loader // Initialize image loader
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this) ImageLoader.getInstance().init(getImageLoaderConfigurations(10));
.memoryCache(new WeakMemoryCache())
.build();
ImageLoader.getInstance().init(config);
configureRxJavaErrorHandler(); configureRxJavaErrorHandler();
} }
@ -122,6 +121,12 @@ public class App extends Application {
}); });
} }
private ImageLoaderConfiguration getImageLoaderConfigurations(final int memoryCacheSizeMb) {
return new ImageLoaderConfiguration.Builder(this)
.memoryCache(new LRULimitedMemoryCache(memoryCacheSizeMb * 1024 * 1024))
.build();
}
private void initACRA() { private void initACRA() {
try { try {
final ACRAConfiguration acraConfig = new ConfigurationBuilder(this) final ACRAConfiguration acraConfig = new ConfigurationBuilder(this)

View File

@ -1,5 +1,6 @@
package org.schabi.newpipe.fragments.local; package org.schabi.newpipe.fragments.local;
import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
@ -25,6 +26,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
public final class PlaylistAppendDialog extends PlaylistDialog { public final class PlaylistAppendDialog extends PlaylistDialog {
private static final String TAG = PlaylistAppendDialog.class.getCanonicalName(); private static final String TAG = PlaylistAppendDialog.class.getCanonicalName();
@ -32,6 +34,8 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
private RecyclerView playlistRecyclerView; private RecyclerView playlistRecyclerView;
private LocalItemListAdapter playlistAdapter; private LocalItemListAdapter playlistAdapter;
private Disposable playlistReactor;
public static PlaylistAppendDialog fromStreamInfo(final StreamInfo info) { public static PlaylistAppendDialog fromStreamInfo(final StreamInfo info) {
PlaylistAppendDialog dialog = new PlaylistAppendDialog(); PlaylistAppendDialog dialog = new PlaylistAppendDialog();
dialog.setInfo(Collections.singletonList(new StreamEntity(info))); dialog.setInfo(Collections.singletonList(new StreamEntity(info)));
@ -68,6 +72,15 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
playlistAdapter = new LocalItemListAdapter(getActivity()); playlistAdapter = new LocalItemListAdapter(getActivity());
} }
@Override
public void onDestroy() {
super.onDestroy();
if (playlistReactor != null) playlistReactor.dispose();
playlistReactor = null;
playlistRecyclerView = null;
playlistAdapter = null;
}
/*////////////////////////////////////////////////////////////////////////// /*//////////////////////////////////////////////////////////////////////////
// Views // Views
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
@ -99,18 +112,20 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
return; return;
final long playlistId = ((PlaylistMetadataEntry) selectedItem).uid; final long playlistId = ((PlaylistMetadataEntry) selectedItem).uid;
final Toast successToast = Toast.makeText(getContext(), @SuppressLint("ShowToast")
R.string.playlist_add_stream_success, Toast.LENGTH_SHORT); final Toast successToast = Toast.makeText(getContext(), R.string.playlist_add_stream_success,
Toast.LENGTH_SHORT);
playlistManager.appendToPlaylist(playlistId, getStreams()) playlistManager.appendToPlaylist(playlistId, getStreams())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(ignored -> successToast.show()); .doOnDispose(successToast::show)
.subscribe(ignored -> {});
getDialog().dismiss(); getDialog().dismiss();
} }
}); });
playlistManager.getPlaylists() playlistReactor = playlistManager.getPlaylists()
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(metadataEntries -> { .subscribe(metadataEntries -> {
if (metadataEntries.isEmpty()) { if (metadataEntries.isEmpty()) {
@ -118,9 +133,13 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
return; return;
} }
playlistAdapter.clearStreamItemList(); if (playlistAdapter != null) {
playlistAdapter.addItems(metadataEntries); playlistAdapter.clearStreamItemList();
playlistRecyclerView.setVisibility(View.VISIBLE); playlistAdapter.addItems(metadataEntries);
}
if (playlistRecyclerView != null) {
playlistRecyclerView.setVisibility(View.VISIBLE);
}
}); });
} }