1
0
mirror of https://github.com/TeamNewPipe/NewPipe synced 2024-12-24 00:50:32 +00:00

-Fixed memory leak due to image loader overusing memory cache.

-Added disk cache for local item loading.
This commit is contained in:
John Zhen Mo 2018-01-29 18:06:48 -08:00
parent d3160eed9d
commit 6f9deea873
11 changed files with 33 additions and 23 deletions

View File

@ -10,6 +10,7 @@ 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.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;
@ -80,7 +81,9 @@ public class App extends Application {
initNotificationChannel(); initNotificationChannel();
// Initialize image loader // Initialize image loader
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this).build(); ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this)
.memoryCache(new WeakMemoryCache())
.build();
ImageLoader.getInstance().init(config); ImageLoader.getInstance().init(config);
configureRxJavaErrorHandler(); configureRxJavaErrorHandler();

View File

@ -1,8 +1,12 @@
package org.schabi.newpipe.fragments.local; package org.schabi.newpipe.fragments.local;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap;
import android.widget.ImageView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.process.BitmapProcessor;
import org.schabi.newpipe.database.LocalItem; import org.schabi.newpipe.database.LocalItem;
@ -42,8 +46,9 @@ public class LocalItemBuilder {
return context; return context;
} }
public ImageLoader getImageLoader() { public void displayImage(final String url, final ImageView view,
return imageLoader; final DisplayImageOptions options) {
imageLoader.displayImage(url, view, options);
} }
public OnLocalItemGesture<LocalItem> getOnItemSelectedListener() { public OnLocalItemGesture<LocalItem> getOnItemSelectedListener() {

View File

@ -69,10 +69,10 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
localItemBuilder.setOnItemSelectedListener(listener); localItemBuilder.setOnItemSelectedListener(listener);
} }
public void addInfoItemList(List<? extends LocalItem> data) { public void addItems(List<? extends LocalItem> data) {
if (data != null) { if (data != null) {
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "addInfoItemList() before > localItems.size() = " + Log.d(TAG, "addItems() before > localItems.size() = " +
localItems.size() + ", data.size() = " + data.size()); localItems.size() + ", data.size() = " + data.size());
} }
@ -80,7 +80,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
localItems.addAll(data); localItems.addAll(data);
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "addInfoItemList() after > offsetStart = " + offsetStart + Log.d(TAG, "addItems() after > offsetStart = " + offsetStart +
", localItems.size() = " + localItems.size() + ", localItems.size() = " + localItems.size() +
", header = " + header + ", footer = " + footer + ", header = " + header + ", footer = " + footer +
", showFooter = " + showFooter); ", showFooter = " + showFooter);
@ -92,7 +92,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
int footerNow = sizeConsideringHeader(); int footerNow = sizeConsideringHeader();
notifyItemMoved(offsetStart, footerNow); notifyItemMoved(offsetStart, footerNow);
if (DEBUG) Log.d(TAG, "addInfoItemList() footer from " + offsetStart + if (DEBUG) Log.d(TAG, "addItems() footer from " + offsetStart +
" to " + footerNow); " to " + footerNow);
} }
} }

View File

@ -349,7 +349,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
animateView(headerRootLayout, true, 100); animateView(headerRootLayout, true, 100);
animateView(itemsList, true, 300); animateView(itemsList, true, 300);
itemListAdapter.addInfoItemList(result); itemListAdapter.addItems(result);
if (itemsListState != null) { if (itemsListState != null) {
itemsList.getLayoutManager().onRestoreInstanceState(itemsListState); itemsList.getLayoutManager().onRestoreInstanceState(itemsListState);
itemsListState = null; itemsListState = null;

View File

@ -119,7 +119,7 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
} }
playlistAdapter.clearStreamItemList(); playlistAdapter.clearStreamItemList();
playlistAdapter.addInfoItemList(metadataEntries); playlistAdapter.addItems(metadataEntries);
playlistRecyclerView.setVisibility(View.VISIBLE); playlistRecyclerView.setVisibility(View.VISIBLE);
}); });
} }

View File

@ -239,7 +239,7 @@ public class BookmarkFragment extends BaseStateFragment<List<PlaylistMetadataEnt
if (result.isEmpty()) { if (result.isEmpty()) {
showEmptyState(); showEmptyState();
} else { } else {
itemListAdapter.addInfoItemList(infoItemsOf(result)); itemListAdapter.addItems(infoItemsOf(result));
if (itemsListState != null) { if (itemsListState != null) {
itemsList.getLayoutManager().onRestoreInstanceState(itemsListState); itemsList.getLayoutManager().onRestoreInstanceState(itemsListState);
itemsListState = null; itemsListState = null;

View File

@ -249,7 +249,7 @@ public abstract class StatisticsPlaylistFragment
animateView(headerRootLayout, true, 100); animateView(headerRootLayout, true, 100);
animateView(itemsList, true, 300); animateView(itemsList, true, 300);
itemListAdapter.addInfoItemList(processResult(result)); itemListAdapter.addItems(processResult(result));
if (itemsListState != null) { if (itemsListState != null) {
itemsList.getLayoutManager().onRestoreInstanceState(itemsListState); itemsList.getLayoutManager().onRestoreInstanceState(itemsListState);
itemsListState = null; itemsListState = null;

View File

@ -1,10 +1,14 @@
package org.schabi.newpipe.fragments.local.holder; package org.schabi.newpipe.fragments.local.holder;
import android.graphics.Bitmap;
import android.support.annotation.DimenRes;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView;
import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.process.BitmapProcessor;
import org.schabi.newpipe.database.LocalItem; import org.schabi.newpipe.database.LocalItem;
import org.schabi.newpipe.fragments.local.LocalItemBuilder; import org.schabi.newpipe.fragments.local.LocalItemBuilder;
@ -52,5 +56,8 @@ public abstract class LocalItemHolder extends RecyclerView.ViewHolder {
public static final DisplayImageOptions BASE_DISPLAY_IMAGE_OPTIONS = public static final DisplayImageOptions BASE_DISPLAY_IMAGE_OPTIONS =
new DisplayImageOptions.Builder() new DisplayImageOptions.Builder()
.cacheInMemory(true) .cacheInMemory(true)
.cacheOnDisk(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.resetViewBeforeLoading(false)
.build(); .build();
} }

View File

@ -43,8 +43,7 @@ public class LocalPlaylistItemHolder extends LocalItemHolder {
itemStreamCountView.setText(String.valueOf(item.streamCount)); itemStreamCountView.setText(String.valueOf(item.streamCount));
itemUploaderView.setVisibility(View.INVISIBLE); itemUploaderView.setVisibility(View.INVISIBLE);
itemBuilder.getImageLoader().displayImage(item.thumbnailUrl, itemThumbnailView, itemBuilder.displayImage(item.thumbnailUrl, itemThumbnailView, DISPLAY_THUMBNAIL_OPTIONS);
DISPLAY_THUMBNAIL_OPTIONS);
itemView.setOnClickListener(view -> { itemView.setOnClickListener(view -> {
if (itemBuilder.getOnItemSelectedListener() != null) { if (itemBuilder.getOnItemSelectedListener() != null) {

View File

@ -1,5 +1,6 @@
package org.schabi.newpipe.fragments.local.holder; package org.schabi.newpipe.fragments.local.holder;
import android.graphics.Bitmap;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
@ -8,6 +9,7 @@ import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.database.LocalItem; import org.schabi.newpipe.database.LocalItem;
@ -59,8 +61,7 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder {
} }
// Default thumbnail is shown on error, while loading and if the url is empty // Default thumbnail is shown on error, while loading and if the url is empty
itemBuilder.getImageLoader().displayImage(item.thumbnailUrl, itemThumbnailView, itemBuilder.displayImage(item.thumbnailUrl, itemThumbnailView, DISPLAY_THUMBNAIL_OPTIONS);
LocalPlaylistStreamItemHolder.DISPLAY_THUMBNAIL_OPTIONS);
itemView.setOnClickListener(view -> { itemView.setOnClickListener(view -> {
if (itemBuilder.getOnItemSelectedListener() != null) { if (itemBuilder.getOnItemSelectedListener() != null) {

View File

@ -45,8 +45,8 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
public final TextView itemDurationView; public final TextView itemDurationView;
public final TextView itemAdditionalDetails; public final TextView itemAdditionalDetails;
LocalStatisticStreamItemHolder(LocalItemBuilder infoItemBuilder, int layoutId, ViewGroup parent) { public LocalStatisticStreamItemHolder(LocalItemBuilder infoItemBuilder, ViewGroup parent) {
super(infoItemBuilder, layoutId, parent); super(infoItemBuilder, R.layout.list_stream_item, parent);
itemThumbnailView = itemView.findViewById(R.id.itemThumbnailView); itemThumbnailView = itemView.findViewById(R.id.itemThumbnailView);
itemVideoTitleView = itemView.findViewById(R.id.itemVideoTitleView); itemVideoTitleView = itemView.findViewById(R.id.itemVideoTitleView);
@ -55,10 +55,6 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
itemAdditionalDetails = itemView.findViewById(R.id.itemAdditionalDetails); itemAdditionalDetails = itemView.findViewById(R.id.itemAdditionalDetails);
} }
public LocalStatisticStreamItemHolder(LocalItemBuilder infoItemBuilder, ViewGroup parent) {
this(infoItemBuilder, R.layout.list_stream_item, parent);
}
private String getStreamInfoDetailLine(final StreamStatisticsEntry entry, private String getStreamInfoDetailLine(final StreamStatisticsEntry entry,
final DateFormat dateFormat) { final DateFormat dateFormat) {
final String watchCount = Localization.shortViewCount(itemBuilder.getContext(), final String watchCount = Localization.shortViewCount(itemBuilder.getContext(),
@ -88,8 +84,7 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
itemAdditionalDetails.setText(getStreamInfoDetailLine(item, dateFormat)); itemAdditionalDetails.setText(getStreamInfoDetailLine(item, dateFormat));
// Default thumbnail is shown on error, while loading and if the url is empty // Default thumbnail is shown on error, while loading and if the url is empty
itemBuilder.getImageLoader().displayImage(item.thumbnailUrl, itemThumbnailView, itemBuilder.displayImage(item.thumbnailUrl, itemThumbnailView, DISPLAY_THUMBNAIL_OPTIONS);
DISPLAY_THUMBNAIL_OPTIONS);
itemView.setOnClickListener(view -> { itemView.setOnClickListener(view -> {
if (itemBuilder.getOnItemSelectedListener() != null) { if (itemBuilder.getOnItemSelectedListener() != null) {