Fix slowdowns in stream list views
Now the playback state of a stream is loaded only when needed (i.e. when the stream is visible), just as it is done with thumbnails. Removed `StateObjectsListAdapter.java`, which used to load the state of every stream at list instantiation, generating slowdowns and freezes.
This commit is contained in:
parent
5053d470f6
commit
e6617ff8e8
22 changed files with 96 additions and 284 deletions
|
|
@ -76,8 +76,6 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I>
|
|||
}
|
||||
updateFlags = 0;
|
||||
}
|
||||
|
||||
itemsList.post(itemListAdapter::updateStates);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -152,7 +150,6 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I>
|
|||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
itemsList = null;
|
||||
itemListAdapter.dispose();
|
||||
itemListAdapter = null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package org.schabi.newpipe.local;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.GridLayoutManager;
|
||||
|
|
@ -11,7 +12,7 @@ import android.view.ViewGroup;
|
|||
|
||||
import org.schabi.newpipe.database.LocalItem;
|
||||
import org.schabi.newpipe.database.stream.model.StreamStateEntity;
|
||||
import org.schabi.newpipe.info_list.StateObjectsListAdapter;
|
||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||
import org.schabi.newpipe.local.holder.LocalItemHolder;
|
||||
import org.schabi.newpipe.local.holder.LocalPlaylistGridItemHolder;
|
||||
import org.schabi.newpipe.local.holder.LocalPlaylistItemHolder;
|
||||
|
|
@ -49,7 +50,7 @@ import java.util.List;
|
|||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
public class LocalItemListAdapter extends StateObjectsListAdapter {
|
||||
public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
|
||||
private static final String TAG = LocalItemListAdapter.class.getSimpleName();
|
||||
private static final boolean DEBUG = false;
|
||||
|
|
@ -68,6 +69,7 @@ public class LocalItemListAdapter extends StateObjectsListAdapter {
|
|||
|
||||
private final LocalItemBuilder localItemBuilder;
|
||||
private final ArrayList<LocalItem> localItems;
|
||||
private final HistoryRecordManager recordManager;
|
||||
private final DateFormat dateFormat;
|
||||
|
||||
private boolean showFooter = false;
|
||||
|
|
@ -75,12 +77,12 @@ public class LocalItemListAdapter extends StateObjectsListAdapter {
|
|||
private View header = null;
|
||||
private View footer = null;
|
||||
|
||||
public LocalItemListAdapter(Activity activity) {
|
||||
super(activity.getApplicationContext());
|
||||
localItemBuilder = new LocalItemBuilder(activity);
|
||||
public LocalItemListAdapter(Context context) {
|
||||
recordManager = new HistoryRecordManager(context);
|
||||
localItemBuilder = new LocalItemBuilder(context);
|
||||
localItems = new ArrayList<>();
|
||||
dateFormat = DateFormat.getDateInstance(DateFormat.SHORT,
|
||||
Localization.getPreferredLocale(activity));
|
||||
Localization.getPreferredLocale(context));
|
||||
}
|
||||
|
||||
public void setSelectedListener(OnClickGesture<LocalItem> listener) {
|
||||
|
|
@ -93,7 +95,7 @@ public class LocalItemListAdapter extends StateObjectsListAdapter {
|
|||
|
||||
public void addItems(@Nullable List<? extends LocalItem> data) {
|
||||
if (data != null) {
|
||||
loadStatesForLocal(data, localItems.size(), () -> addItemsImpl(data));
|
||||
addItemsImpl(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -124,16 +126,9 @@ public class LocalItemListAdapter extends StateObjectsListAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
public void updateStates() {
|
||||
if (!localItems.isEmpty()) {
|
||||
updateAllLocalStates(localItems);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeItem(final LocalItem data) {
|
||||
final int index = localItems.indexOf(data);
|
||||
localItems.remove(index);
|
||||
removeState(index);
|
||||
notifyItemRemoved(index + (header != null ? 1 : 0));
|
||||
}
|
||||
|
||||
|
|
@ -145,7 +140,6 @@ public class LocalItemListAdapter extends StateObjectsListAdapter {
|
|||
if (actualFrom >= localItems.size() || actualTo >= localItems.size()) return false;
|
||||
|
||||
localItems.add(actualTo, localItems.remove(actualFrom));
|
||||
moveState(actualFrom, actualTo);
|
||||
notifyItemMoved(fromAdapterPosition, toAdapterPosition);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -155,7 +149,6 @@ public class LocalItemListAdapter extends StateObjectsListAdapter {
|
|||
return;
|
||||
}
|
||||
localItems.clear();
|
||||
clearStates();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
|
|
@ -276,7 +269,7 @@ public class LocalItemListAdapter extends StateObjectsListAdapter {
|
|||
// If header isn't null, offset the items by -1
|
||||
if (header != null) position--;
|
||||
|
||||
((LocalItemHolder) holder).updateFromItem(localItems.get(position), getState(position), dateFormat);
|
||||
((LocalItemHolder) holder).updateFromItem(localItems.get(position), recordManager, dateFormat);
|
||||
} else if (holder instanceof HeaderFooterHolder && position == 0 && header != null) {
|
||||
((HeaderFooterHolder) holder).view = header;
|
||||
} else if (holder instanceof HeaderFooterHolder && position == sizeConsideringHeader()
|
||||
|
|
@ -290,11 +283,9 @@ public class LocalItemListAdapter extends StateObjectsListAdapter {
|
|||
if (!payloads.isEmpty() && holder instanceof LocalItemHolder) {
|
||||
for (Object payload : payloads) {
|
||||
if (payload instanceof StreamStateEntity) {
|
||||
((LocalItemHolder) holder).updateState(localItems.get(header == null ? position : position - 1),
|
||||
(StreamStateEntity) payload);
|
||||
((LocalItemHolder) holder).updateState(localItems.get(header == null ? position : position - 1), recordManager);
|
||||
} else if (payload instanceof Boolean) {
|
||||
((LocalItemHolder) holder).updateState(localItems.get(header == null ? position : position - 1),
|
||||
null);
|
||||
((LocalItemHolder) holder).updateState(localItems.get(header == null ? position : position - 1), recordManager);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -302,11 +293,6 @@ public class LocalItemListAdapter extends StateObjectsListAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onItemStateChanged(int position, @Nullable StreamStateEntity state) {
|
||||
notifyItemChanged(header == null ? position : position + 1, state != null ? state : false);
|
||||
}
|
||||
|
||||
public GridLayoutManager.SpanSizeLookup getSpanSizeLookup(final int spanCount) {
|
||||
return new GridLayoutManager.SpanSizeLookup() {
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -113,7 +113,6 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
|
|||
super.onDestroyView();
|
||||
if (playlistReactor != null) playlistReactor.dispose();
|
||||
if (playlistAdapter != null) {
|
||||
playlistAdapter.dispose();
|
||||
playlistAdapter.unsetSelectedListener();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import android.view.ViewGroup;
|
|||
import org.schabi.newpipe.database.LocalItem;
|
||||
import org.schabi.newpipe.database.stream.model.StreamStateEntity;
|
||||
import org.schabi.newpipe.local.LocalItemBuilder;
|
||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||
|
||||
import java.text.DateFormat;
|
||||
|
||||
|
|
@ -40,8 +41,8 @@ public abstract class LocalItemHolder extends RecyclerView.ViewHolder {
|
|||
this.itemBuilder = itemBuilder;
|
||||
}
|
||||
|
||||
public abstract void updateFromItem(final LocalItem item, @Nullable final StreamStateEntity state, final DateFormat dateFormat);
|
||||
public abstract void updateFromItem(final LocalItem item, HistoryRecordManager historyRecordManager, final DateFormat dateFormat);
|
||||
|
||||
public void updateState(final LocalItem localItem, @Nullable final StreamStateEntity state) {
|
||||
public void updateState(final LocalItem localItem, HistoryRecordManager historyRecordManager) {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import org.schabi.newpipe.database.LocalItem;
|
|||
import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry;
|
||||
import org.schabi.newpipe.database.stream.model.StreamStateEntity;
|
||||
import org.schabi.newpipe.local.LocalItemBuilder;
|
||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||
import org.schabi.newpipe.util.ImageDisplayConstants;
|
||||
|
||||
import java.text.DateFormat;
|
||||
|
|
@ -23,7 +24,7 @@ public class LocalPlaylistItemHolder extends PlaylistItemHolder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateFromItem(final LocalItem localItem, @Nullable final StreamStateEntity state, final DateFormat dateFormat) {
|
||||
public void updateFromItem(final LocalItem localItem, HistoryRecordManager historyRecordManager, final DateFormat dateFormat) {
|
||||
if (!(localItem instanceof PlaylistMetadataEntry)) return;
|
||||
final PlaylistMetadataEntry item = (PlaylistMetadataEntry) localItem;
|
||||
|
||||
|
|
@ -34,6 +35,6 @@ public class LocalPlaylistItemHolder extends PlaylistItemHolder {
|
|||
itemBuilder.displayImage(item.thumbnailUrl, itemThumbnailView,
|
||||
ImageDisplayConstants.DISPLAY_PLAYLIST_OPTIONS);
|
||||
|
||||
super.updateFromItem(localItem, state, dateFormat);
|
||||
super.updateFromItem(localItem, historyRecordManager, dateFormat);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,12 +14,14 @@ import org.schabi.newpipe.database.playlist.PlaylistStreamEntry;
|
|||
import org.schabi.newpipe.database.stream.model.StreamStateEntity;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.local.LocalItemBuilder;
|
||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||
import org.schabi.newpipe.util.AnimationUtils;
|
||||
import org.schabi.newpipe.util.ImageDisplayConstants;
|
||||
import org.schabi.newpipe.util.Localization;
|
||||
import org.schabi.newpipe.views.AnimatedProgressBar;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class LocalPlaylistStreamItemHolder extends LocalItemHolder {
|
||||
|
|
@ -47,7 +49,7 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateFromItem(final LocalItem localItem, @Nullable final StreamStateEntity state, final DateFormat dateFormat) {
|
||||
public void updateFromItem(final LocalItem localItem, HistoryRecordManager historyRecordManager, final DateFormat dateFormat) {
|
||||
if (!(localItem instanceof PlaylistStreamEntry)) return;
|
||||
final PlaylistStreamEntry item = (PlaylistStreamEntry) localItem;
|
||||
|
||||
|
|
@ -60,6 +62,8 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder {
|
|||
itemDurationView.setBackgroundColor(ContextCompat.getColor(itemBuilder.getContext(),
|
||||
R.color.duration_background_color));
|
||||
itemDurationView.setVisibility(View.VISIBLE);
|
||||
|
||||
StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{ add(localItem); }}).blockingGet().get(0);
|
||||
if (state != null) {
|
||||
itemProgressView.setVisibility(View.VISIBLE);
|
||||
itemProgressView.setMax((int) item.duration);
|
||||
|
|
@ -94,9 +98,11 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateState(LocalItem localItem, @Nullable StreamStateEntity state) {
|
||||
public void updateState(LocalItem localItem, HistoryRecordManager historyRecordManager) {
|
||||
if (!(localItem instanceof PlaylistStreamEntry)) return;
|
||||
final PlaylistStreamEntry item = (PlaylistStreamEntry) localItem;
|
||||
|
||||
StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{ add(localItem); }}).blockingGet().get(0);
|
||||
if (state != null && item.duration > 0) {
|
||||
itemProgressView.setMax((int) item.duration);
|
||||
if (itemProgressView.getVisibility() == View.VISIBLE) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package org.schabi.newpipe.local.holder;
|
|||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
|
@ -13,12 +14,14 @@ import org.schabi.newpipe.database.stream.StreamStatisticsEntry;
|
|||
import org.schabi.newpipe.database.stream.model.StreamStateEntity;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.local.LocalItemBuilder;
|
||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||
import org.schabi.newpipe.util.AnimationUtils;
|
||||
import org.schabi.newpipe.util.ImageDisplayConstants;
|
||||
import org.schabi.newpipe.util.Localization;
|
||||
import org.schabi.newpipe.views.AnimatedProgressBar;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/*
|
||||
|
|
@ -76,7 +79,7 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateFromItem(final LocalItem localItem, @Nullable final StreamStateEntity state, final DateFormat dateFormat) {
|
||||
public void updateFromItem(final LocalItem localItem, HistoryRecordManager historyRecordManager, final DateFormat dateFormat) {
|
||||
if (!(localItem instanceof StreamStatisticsEntry)) return;
|
||||
final StreamStatisticsEntry item = (StreamStatisticsEntry) localItem;
|
||||
|
||||
|
|
@ -88,6 +91,8 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
|
|||
itemDurationView.setBackgroundColor(ContextCompat.getColor(itemBuilder.getContext(),
|
||||
R.color.duration_background_color));
|
||||
itemDurationView.setVisibility(View.VISIBLE);
|
||||
|
||||
StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{ add(localItem); }}).blockingGet().get(0);
|
||||
if (state != null) {
|
||||
itemProgressView.setVisibility(View.VISIBLE);
|
||||
itemProgressView.setMax((int) item.duration);
|
||||
|
|
@ -124,9 +129,11 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateState(LocalItem localItem, @Nullable StreamStateEntity state) {
|
||||
public void updateState(LocalItem localItem, HistoryRecordManager historyRecordManager) {
|
||||
if (!(localItem instanceof StreamStatisticsEntry)) return;
|
||||
final StreamStatisticsEntry item = (StreamStatisticsEntry) localItem;
|
||||
|
||||
StreamStateEntity state = historyRecordManager.loadLocalStreamStateBatch(new ArrayList<LocalItem>() {{ add(localItem); }}).blockingGet().get(0);
|
||||
if (state != null && item.duration > 0) {
|
||||
itemProgressView.setMax((int) item.duration);
|
||||
if (itemProgressView.getVisibility() == View.VISIBLE) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import org.schabi.newpipe.R;
|
|||
import org.schabi.newpipe.database.LocalItem;
|
||||
import org.schabi.newpipe.database.stream.model.StreamStateEntity;
|
||||
import org.schabi.newpipe.local.LocalItemBuilder;
|
||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||
|
||||
import java.text.DateFormat;
|
||||
|
||||
|
|
@ -33,7 +34,7 @@ public abstract class PlaylistItemHolder extends LocalItemHolder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateFromItem(final LocalItem localItem, @Nullable final StreamStateEntity state, final DateFormat dateFormat) {
|
||||
public void updateFromItem(final LocalItem localItem, HistoryRecordManager historyRecordManager, final DateFormat dateFormat) {
|
||||
itemView.setOnClickListener(view -> {
|
||||
if (itemBuilder.getOnItemSelectedListener() != null) {
|
||||
itemBuilder.getOnItemSelectedListener().selected(localItem);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
|
|||
import org.schabi.newpipe.database.stream.model.StreamStateEntity;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.local.LocalItemBuilder;
|
||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||
import org.schabi.newpipe.util.ImageDisplayConstants;
|
||||
import org.schabi.newpipe.util.Localization;
|
||||
|
||||
|
|
@ -23,7 +24,7 @@ public class RemotePlaylistItemHolder extends PlaylistItemHolder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateFromItem(final LocalItem localItem, @Nullable final StreamStateEntity state, final DateFormat dateFormat) {
|
||||
public void updateFromItem(final LocalItem localItem, HistoryRecordManager historyRecordManager, final DateFormat dateFormat) {
|
||||
if (!(localItem instanceof PlaylistRemoteEntity)) return;
|
||||
final PlaylistRemoteEntity item = (PlaylistRemoteEntity) localItem;
|
||||
|
||||
|
|
@ -35,6 +36,6 @@ public class RemotePlaylistItemHolder extends PlaylistItemHolder {
|
|||
itemBuilder.displayImage(item.getThumbnailUrl(), itemThumbnailView,
|
||||
ImageDisplayConstants.DISPLAY_PLAYLIST_OPTIONS);
|
||||
|
||||
super.updateFromItem(localItem, state, dateFormat);
|
||||
super.updateFromItem(localItem, historyRecordManager, dateFormat);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,7 +130,6 @@ public class SubscriptionFragment extends BaseStateFragment<List<SubscriptionEnt
|
|||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
infoListAdapter.dispose();
|
||||
super.onDetach();
|
||||
}
|
||||
|
||||
|
|
@ -153,8 +152,6 @@ public class SubscriptionFragment extends BaseStateFragment<List<SubscriptionEnt
|
|||
}
|
||||
updateFlags = 0;
|
||||
}
|
||||
|
||||
itemsList.post(infoListAdapter::updateStates);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue