Reorganize Episode Fragments lifecycle
This uses the existing android lifecycle methods to avoid having to do null checks and state saving in various places.
This commit is contained in:
parent
aabe370db3
commit
bbcec5d0aa
@ -29,6 +29,7 @@ import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
@ -43,6 +44,7 @@ import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadRequest;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadService;
|
||||
import de.danoeh.antennapod.core.service.download.Downloader;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
@ -80,11 +82,10 @@ public class AllEpisodesFragment extends Fragment {
|
||||
private ProgressBar progLoading;
|
||||
EmptyViewHandler emptyView;
|
||||
|
||||
List<FeedItem> episodes;
|
||||
private List<Downloader> downloaderList;
|
||||
|
||||
private boolean itemsLoaded = false;
|
||||
private boolean viewsCreated = false;
|
||||
@NonNull
|
||||
List<FeedItem> episodes = new ArrayList<>();
|
||||
@NonNull
|
||||
private List<Downloader> downloaderList = new ArrayList<>();
|
||||
|
||||
private boolean isUpdatingFeeds;
|
||||
boolean isMenuInvalidationAllowed = false;
|
||||
@ -100,26 +101,18 @@ public class AllEpisodesFragment extends Fragment {
|
||||
return DEFAULT_PREF_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
setHasOptionsMenu(true);
|
||||
EventDistributor.getInstance().register(contentUpdate);
|
||||
if (viewsCreated && itemsLoaded) {
|
||||
onFragmentLoaded();
|
||||
}
|
||||
EventBus.getDefault().register(this);
|
||||
loadItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
loadItems();
|
||||
registerForContextMenu(recyclerView);
|
||||
}
|
||||
|
||||
@ -140,12 +133,6 @@ public class AllEpisodesFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
resetViewState();
|
||||
}
|
||||
|
||||
private void saveScrollPosition() {
|
||||
int firstItem = layoutManager.findFirstVisibleItemPosition();
|
||||
View firstItemView = layoutManager.findViewByPosition(firstItem);
|
||||
@ -177,12 +164,6 @@ public class AllEpisodesFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
void resetViewState() {
|
||||
viewsCreated = false;
|
||||
listAdapter = null;
|
||||
}
|
||||
|
||||
|
||||
private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker =
|
||||
() -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
|
||||
|
||||
@ -192,28 +173,26 @@ public class AllEpisodesFragment extends Fragment {
|
||||
return;
|
||||
}
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
if (itemsLoaded) {
|
||||
inflater.inflate(R.menu.episodes, menu);
|
||||
inflater.inflate(R.menu.episodes, menu);
|
||||
|
||||
MenuItem searchItem = menu.findItem(R.id.action_search);
|
||||
final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
|
||||
MenuItemUtils.adjustTextColor(getActivity(), sv);
|
||||
sv.setQueryHint(getString(R.string.search_hint));
|
||||
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String s) {
|
||||
sv.clearFocus();
|
||||
((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance(s));
|
||||
return true;
|
||||
}
|
||||
MenuItem searchItem = menu.findItem(R.id.action_search);
|
||||
final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
|
||||
MenuItemUtils.adjustTextColor(getActivity(), sv);
|
||||
sv.setQueryHint(getString(R.string.search_hint));
|
||||
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String s) {
|
||||
sv.clearFocus();
|
||||
((MainActivity) requireActivity()).loadChildFragment(SearchFragment.newInstance(s));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(String s) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
|
||||
}
|
||||
@Override
|
||||
public boolean onQueryTextChange(String s) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -221,11 +200,11 @@ public class AllEpisodesFragment extends Fragment {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
MenuItem markAllRead = menu.findItem(R.id.mark_all_read_item);
|
||||
if (markAllRead != null) {
|
||||
markAllRead.setVisible(!showOnlyNewEpisodes() && episodes != null && !episodes.isEmpty());
|
||||
markAllRead.setVisible(!showOnlyNewEpisodes() && !episodes.isEmpty());
|
||||
}
|
||||
MenuItem markAllSeen = menu.findItem(R.id.mark_all_seen_item);
|
||||
if (markAllSeen != null) {
|
||||
markAllSeen.setVisible(showOnlyNewEpisodes() && episodes != null && !episodes.isEmpty());
|
||||
markAllSeen.setVisible(showOnlyNewEpisodes() && !episodes.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
@ -286,7 +265,7 @@ public class AllEpisodesFragment extends Fragment {
|
||||
return true; // avoids that the position is reset when we need it in the submenu
|
||||
}
|
||||
|
||||
if (listAdapter == null || listAdapter.getSelectedItem() == null) {
|
||||
if (listAdapter.getSelectedItem() == null) {
|
||||
Log.i(TAG, "Selected item or listAdapter was null, ignoring selection");
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
@ -305,85 +284,74 @@ public class AllEpisodesFragment extends Fragment {
|
||||
return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return onCreateViewHelper(inflater, container, savedInstanceState,
|
||||
R.layout.all_episodes_fragment);
|
||||
}
|
||||
|
||||
View onCreateViewHelper(LayoutInflater inflater,
|
||||
ViewGroup container,
|
||||
Bundle savedInstanceState,
|
||||
int fragmentResource) {
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
View root = inflater.inflate(R.layout.all_episodes_fragment, container, false);
|
||||
|
||||
View root = inflater.inflate(fragmentResource, container, false);
|
||||
|
||||
layoutManager = new LinearLayoutManager(getActivity());
|
||||
recyclerView = root.findViewById(android.R.id.list);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
recyclerView.setHasFixedSize(true);
|
||||
recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).build());
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
|
||||
RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator();
|
||||
if (animator instanceof SimpleItemAnimator) {
|
||||
((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
|
||||
}
|
||||
layoutManager = new LinearLayoutManager(getActivity());
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
recyclerView.setHasFixedSize(true);
|
||||
recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).build());
|
||||
|
||||
progLoading = root.findViewById(R.id.progLoading);
|
||||
|
||||
if (!itemsLoaded) {
|
||||
progLoading.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
viewsCreated = true;
|
||||
|
||||
if (itemsLoaded) {
|
||||
onFragmentLoaded();
|
||||
}
|
||||
progLoading.setVisibility(View.VISIBLE);
|
||||
|
||||
emptyView = new EmptyViewHandler(getContext());
|
||||
emptyView.attachToRecyclerView(recyclerView);
|
||||
emptyView.setTitle(R.string.no_all_episodes_head_label);
|
||||
emptyView.setMessage(R.string.no_all_episodes_label);
|
||||
emptyView.hide();
|
||||
|
||||
createRecycleAdapter();
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void onFragmentLoaded() {
|
||||
if (episodes != null && episodes.size() > 0) {
|
||||
if (listAdapter == null) {
|
||||
MainActivity mainActivity = (MainActivity) getActivity();
|
||||
listAdapter = new AllEpisodesRecycleAdapter(mainActivity, itemAccess, showOnlyNewEpisodes());
|
||||
listAdapter.setHasStableIds(true);
|
||||
recyclerView.setAdapter(listAdapter);
|
||||
emptyView.updateAdapter(listAdapter);
|
||||
}
|
||||
if (episodes.size() > 0) {
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
listAdapter.notifyDataSetChanged();
|
||||
} else {
|
||||
listAdapter = null;
|
||||
createRecycleAdapter();
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
emptyView.updateAdapter(listAdapter);
|
||||
}
|
||||
|
||||
restoreScrollPosition();
|
||||
getActivity().supportInvalidateOptionsMenu();
|
||||
updateShowOnlyEpisodesListViewState();
|
||||
requireActivity().invalidateOptionsMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently, we need to recreate the list adapter in order to be able to undo last item via the
|
||||
* snackbar. See #3084 for details.
|
||||
*/
|
||||
private void createRecycleAdapter() {
|
||||
MainActivity mainActivity = (MainActivity) getActivity();
|
||||
listAdapter = new AllEpisodesRecycleAdapter(mainActivity, itemAccess, showOnlyNewEpisodes());
|
||||
listAdapter.setHasStableIds(true);
|
||||
recyclerView.setAdapter(listAdapter);
|
||||
emptyView.updateAdapter(listAdapter);
|
||||
}
|
||||
|
||||
private final AllEpisodesRecycleAdapter.ItemAccess itemAccess = new AllEpisodesRecycleAdapter.ItemAccess() {
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
if (episodes != null) {
|
||||
return episodes.size();
|
||||
}
|
||||
return 0;
|
||||
return episodes.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeedItem getItem(int position) {
|
||||
if (episodes != null && 0 <= position && position < episodes.size()) {
|
||||
if (0 <= position && position < episodes.size()) {
|
||||
return episodes.get(position);
|
||||
}
|
||||
return null;
|
||||
@ -391,9 +359,6 @@ public class AllEpisodesFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public LongList getItemsIds() {
|
||||
if (episodes == null) {
|
||||
return new LongList(0);
|
||||
}
|
||||
LongList ids = new LongList(episodes.size());
|
||||
for (FeedItem episode : episodes) {
|
||||
ids.add(episode.getId());
|
||||
@ -403,12 +368,11 @@ public class AllEpisodesFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public int getItemDownloadProgressPercent(FeedItem item) {
|
||||
if (downloaderList != null) {
|
||||
for (Downloader downloader : downloaderList) {
|
||||
if (downloader.getDownloadRequest().getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
|
||||
&& downloader.getDownloadRequest().getFeedfileId() == item.getMedia().getId()) {
|
||||
return downloader.getDownloadRequest().getProgressPercent();
|
||||
}
|
||||
for (Downloader downloader : downloaderList) {
|
||||
DownloadRequest downloadRequest = downloader.getDownloadRequest();
|
||||
if (downloadRequest.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
|
||||
&& downloadRequest.getFeedfileId() == item.getMedia().getId()) {
|
||||
return downloadRequest.getProgressPercent();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -422,9 +386,6 @@ public class AllEpisodesFragment extends Fragment {
|
||||
@Override
|
||||
public LongList getQueueIds() {
|
||||
LongList queueIds = new LongList();
|
||||
if (episodes == null) {
|
||||
return queueIds;
|
||||
}
|
||||
for (FeedItem item : episodes) {
|
||||
if (item.isTagged(FeedItem.TAG_QUEUE)) {
|
||||
queueIds.add(item.getId());
|
||||
@ -438,12 +399,6 @@ public class AllEpisodesFragment extends Fragment {
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onEventMainThread(FeedItemEvent event) {
|
||||
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
|
||||
if (episodes == null) {
|
||||
return;
|
||||
} else if (listAdapter == null) {
|
||||
loadItems();
|
||||
return;
|
||||
}
|
||||
for (FeedItem item : event.items) {
|
||||
int pos = FeedItemUtil.indexOfItemWithId(episodes, item.getId());
|
||||
if (pos >= 0) {
|
||||
@ -468,11 +423,7 @@ public class AllEpisodesFragment extends Fragment {
|
||||
DownloaderUpdate update = event.update;
|
||||
downloaderList = update.downloaders;
|
||||
if (isMenuInvalidationAllowed && isUpdatingFeeds != update.feedIds.length > 0) {
|
||||
getActivity().supportInvalidateOptionsMenu();
|
||||
}
|
||||
if (listAdapter == null) {
|
||||
loadItems();
|
||||
return;
|
||||
requireActivity().invalidateOptionsMenu();
|
||||
}
|
||||
if (update.mediaIds.length > 0) {
|
||||
for (long mediaId : update.mediaIds) {
|
||||
@ -490,24 +441,16 @@ public class AllEpisodesFragment extends Fragment {
|
||||
if ((arg & EVENTS) != 0) {
|
||||
loadItems();
|
||||
if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()) {
|
||||
getActivity().supportInvalidateOptionsMenu();
|
||||
requireActivity().invalidateOptionsMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void updateShowOnlyEpisodesListViewState() {
|
||||
}
|
||||
|
||||
void loadItems() {
|
||||
if (disposable != null) {
|
||||
disposable.dispose();
|
||||
}
|
||||
if (viewsCreated && !itemsLoaded) {
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
emptyView.hide();
|
||||
progLoading.setVisibility(View.VISIBLE);
|
||||
}
|
||||
disposable = Observable.fromCallable(this::loadData)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -515,10 +458,7 @@ public class AllEpisodesFragment extends Fragment {
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
progLoading.setVisibility(View.GONE);
|
||||
episodes = data;
|
||||
itemsLoaded = true;
|
||||
if (viewsCreated) {
|
||||
onFragmentLoaded();
|
||||
}
|
||||
onFragmentLoaded();
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package de.danoeh.antennapod.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||
@ -27,7 +28,6 @@ import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
public class FavoriteEpisodesFragment extends AllEpisodesFragment {
|
||||
|
||||
private static final String TAG = "FavoriteEpisodesFrag";
|
||||
|
||||
private static final String PREF_NAME = "PrefFavoriteEpisodesFragment";
|
||||
|
||||
@Override
|
||||
@ -42,19 +42,14 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment {
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(FavoritesEvent event) {
|
||||
Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
|
||||
Log.d(TAG, String.format("onEvent() called with: event = [%s]", event));
|
||||
loadItems();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected void resetViewState() {
|
||||
super.resetViewState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View root = super.onCreateViewHelper(inflater, container, savedInstanceState,
|
||||
R.layout.all_episodes_fragment);
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View root = super.onCreateView(inflater, container, savedInstanceState);
|
||||
emptyView.setTitle(R.string.no_fav_episodes_head_label);
|
||||
emptyView.setMessage(R.string.no_fav_episodes_label);
|
||||
|
||||
@ -67,7 +62,7 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment {
|
||||
@Override
|
||||
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
|
||||
AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder) viewHolder;
|
||||
Log.d(TAG, "remove(" + holder.getItemId() + ")");
|
||||
Log.d(TAG, String.format("remove(%s)", holder.getItemId()));
|
||||
|
||||
if (disposable != null) {
|
||||
disposable.dispose();
|
||||
@ -88,6 +83,7 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment {
|
||||
return root;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected List<FeedItem> loadData() {
|
||||
return DBReader.getFavoriteItemsList();
|
||||
|
@ -1,6 +1,7 @@
|
||||
package de.danoeh.antennapod.fragment;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.helper.ItemTouchHelper;
|
||||
import android.view.LayoutInflater;
|
||||
@ -33,20 +34,15 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
|
||||
return PREF_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetViewState() {
|
||||
super.resetViewState();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldUpdatedItemRemainInList(FeedItem item) {
|
||||
return item.isNew();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View root = super.onCreateViewHelper(inflater, container, savedInstanceState,
|
||||
R.layout.all_episodes_fragment);
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View root = super.onCreateView(inflater, container, savedInstanceState);
|
||||
emptyView.setTitle(R.string.no_new_episodes_head_label);
|
||||
emptyView.setMessage(R.string.no_new_episodes_label);
|
||||
|
||||
@ -96,6 +92,7 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
|
||||
return root;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected List<FeedItem> loadData() {
|
||||
return DBReader.getNewItemsList();
|
||||
|
@ -1,5 +1,7 @@
|
||||
package de.danoeh.antennapod.core.event;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@ -11,6 +13,7 @@ import de.danoeh.antennapod.core.util.LongList;
|
||||
public class DownloaderUpdate {
|
||||
|
||||
/* Downloaders that are currently running */
|
||||
@NonNull
|
||||
public final List<Downloader> downloaders;
|
||||
|
||||
/**
|
||||
@ -25,7 +28,7 @@ public class DownloaderUpdate {
|
||||
*/
|
||||
public final long[] mediaIds;
|
||||
|
||||
public DownloaderUpdate(List<Downloader> downloaders) {
|
||||
DownloaderUpdate(@NonNull List<Downloader> downloaders) {
|
||||
this.downloaders = downloaders;
|
||||
LongList feedIds1 = new LongList(), mediaIds1 = new LongList();
|
||||
for(Downloader d1 : downloaders) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user