Merge pull request #3194 from andersonvom/2747-completed-downloads-update

Reorganize fragment lifecycle
This commit is contained in:
H. Lehmann 2019-07-11 13:06:23 +02:00 committed by GitHub
commit 14c9fd2fa2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 364 additions and 599 deletions

View File

@ -21,11 +21,15 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration; import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
@ -40,6 +44,7 @@ import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.UserPreferences; 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.DownloadService;
import de.danoeh.antennapod.core.service.download.Downloader; import de.danoeh.antennapod.core.service.download.Downloader;
import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBReader;
@ -50,15 +55,11 @@ import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
import de.danoeh.antennapod.menuhandler.MenuItemUtils; import de.danoeh.antennapod.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.view.EmptyViewHandler; import de.danoeh.antennapod.view.EmptyViewHandler;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable; import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
/** /**
* Shows unread or recently published episodes * Shows unread or recently published episodes
@ -81,11 +82,10 @@ public class AllEpisodesFragment extends Fragment {
private ProgressBar progLoading; private ProgressBar progLoading;
EmptyViewHandler emptyView; EmptyViewHandler emptyView;
List<FeedItem> episodes; @NonNull
private List<Downloader> downloaderList; List<FeedItem> episodes = new ArrayList<>();
@NonNull
private boolean itemsLoaded = false; private List<Downloader> downloaderList = new ArrayList<>();
private boolean viewsCreated = false;
private boolean isUpdatingFeeds; private boolean isUpdatingFeeds;
boolean isMenuInvalidationAllowed = false; boolean isMenuInvalidationAllowed = false;
@ -93,29 +93,26 @@ public class AllEpisodesFragment extends Fragment {
Disposable disposable; Disposable disposable;
private LinearLayoutManager layoutManager; private LinearLayoutManager layoutManager;
boolean showOnlyNewEpisodes() { return false; } boolean showOnlyNewEpisodes() {
String getPrefName() { return DEFAULT_PREF_NAME; } return false;
}
@Override String getPrefName() {
public void onCreate(Bundle savedInstanceState) { return DEFAULT_PREF_NAME;
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
} }
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
setHasOptionsMenu(true);
EventDistributor.getInstance().register(contentUpdate); EventDistributor.getInstance().register(contentUpdate);
if (viewsCreated && itemsLoaded) {
onFragmentLoaded();
}
EventBus.getDefault().register(this); EventBus.getDefault().register(this);
loadItems();
} }
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
loadItems();
registerForContextMenu(recyclerView); registerForContextMenu(recyclerView);
} }
@ -136,17 +133,11 @@ public class AllEpisodesFragment extends Fragment {
} }
} }
@Override
public void onDestroyView() {
super.onDestroyView();
resetViewState();
}
private void saveScrollPosition() { private void saveScrollPosition() {
int firstItem = layoutManager.findFirstVisibleItemPosition(); int firstItem = layoutManager.findFirstVisibleItemPosition();
View firstItemView = layoutManager.findViewByPosition(firstItem); View firstItemView = layoutManager.findViewByPosition(firstItem);
float topOffset; float topOffset;
if(firstItemView == null) { if (firstItemView == null) {
topOffset = 0; topOffset = 0;
} else { } else {
topOffset = firstItemView.getTop(); topOffset = firstItemView.getTop();
@ -173,43 +164,35 @@ public class AllEpisodesFragment extends Fragment {
} }
} }
void resetViewState() {
viewsCreated = false;
listAdapter = null;
}
private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker = private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker =
() -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds(); () -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
@Override @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if(!isAdded()) { if (!isAdded()) {
return; return;
} }
super.onCreateOptionsMenu(menu, inflater); 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); MenuItem searchItem = menu.findItem(R.id.action_search);
final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem); final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
MenuItemUtils.adjustTextColor(getActivity(), sv); MenuItemUtils.adjustTextColor(getActivity(), sv);
sv.setQueryHint(getString(R.string.search_hint)); sv.setQueryHint(getString(R.string.search_hint));
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override @Override
public boolean onQueryTextSubmit(String s) { public boolean onQueryTextSubmit(String s) {
sv.clearFocus(); sv.clearFocus();
((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance(s)); ((MainActivity) requireActivity()).loadChildFragment(SearchFragment.newInstance(s));
return true; return true;
} }
@Override @Override
public boolean onQueryTextChange(String s) { public boolean onQueryTextChange(String s) {
return false; return false;
} }
}); });
isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker); isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
}
} }
@Override @Override
@ -217,11 +200,11 @@ public class AllEpisodesFragment extends Fragment {
super.onPrepareOptionsMenu(menu); super.onPrepareOptionsMenu(menu);
MenuItem markAllRead = menu.findItem(R.id.mark_all_read_item); MenuItem markAllRead = menu.findItem(R.id.mark_all_read_item);
if (markAllRead != null) { 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); MenuItem markAllSeen = menu.findItem(R.id.mark_all_seen_item);
if(markAllSeen != null) { if (markAllSeen != null) {
markAllSeen.setVisible(showOnlyNewEpisodes() && episodes != null && !episodes.isEmpty()); markAllSeen.setVisible(showOnlyNewEpisodes() && !episodes.isEmpty());
} }
} }
@ -278,14 +261,14 @@ public class AllEpisodesFragment extends Fragment {
if (!getUserVisibleHint()) { if (!getUserVisibleHint()) {
return false; return false;
} }
if(!isVisible()) { if (!isVisible()) {
return false; return false;
} }
if(item.getItemId() == R.id.share_item) { if (item.getItemId() == R.id.share_item) {
return true; // avoids that the position is reset when we need it in the submenu 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"); Log.i(TAG, "Selected item or listAdapter was null, ignoring selection");
return super.onContextItemSelected(item); return super.onContextItemSelected(item);
} }
@ -304,85 +287,72 @@ public class AllEpisodesFragment extends Fragment {
return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem); return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
} }
@NonNull
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(@NonNull 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) {
super.onCreateView(inflater, container, 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 = 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(); RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator();
if (animator instanceof SimpleItemAnimator) { if (animator instanceof SimpleItemAnimator) {
((SimpleItemAnimator) animator).setSupportsChangeAnimations(false); ((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); progLoading = root.findViewById(R.id.progLoading);
progLoading.setVisibility(View.VISIBLE);
if (!itemsLoaded) {
progLoading.setVisibility(View.VISIBLE);
}
viewsCreated = true;
if (itemsLoaded) {
onFragmentLoaded();
}
emptyView = new EmptyViewHandler(getContext()); emptyView = new EmptyViewHandler(getContext());
emptyView.attachToRecyclerView(recyclerView); emptyView.attachToRecyclerView(recyclerView);
emptyView.setTitle(R.string.no_all_episodes_head_label); emptyView.setTitle(R.string.no_all_episodes_head_label);
emptyView.setMessage(R.string.no_all_episodes_label); emptyView.setMessage(R.string.no_all_episodes_label);
createRecycleAdapter(recyclerView, emptyView);
emptyView.hide();
return root; return root;
} }
private void onFragmentLoaded() { private void onFragmentLoaded(List<FeedItem> episodes) {
if (episodes != null && episodes.size() > 0) { this.episodes = episodes;
if (listAdapter == null) { listAdapter.notifyDataSetChanged();
MainActivity mainActivity = (MainActivity) getActivity();
listAdapter = new AllEpisodesRecycleAdapter(mainActivity, itemAccess, showOnlyNewEpisodes()); if (episodes.size() == 0) {
listAdapter.setHasStableIds(true); createRecycleAdapter(recyclerView, emptyView);
recyclerView.setAdapter(listAdapter);
emptyView.updateAdapter(listAdapter);
}
recyclerView.setVisibility(View.VISIBLE);
listAdapter.notifyDataSetChanged();
} else {
listAdapter = null;
recyclerView.setVisibility(View.GONE);
emptyView.updateAdapter(listAdapter);
} }
restoreScrollPosition(); restoreScrollPosition();
getActivity().supportInvalidateOptionsMenu(); requireActivity().invalidateOptionsMenu();
updateShowOnlyEpisodesListViewState(); }
/**
* 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(RecyclerView recyclerView, EmptyViewHandler emptyViewHandler) {
MainActivity mainActivity = (MainActivity) getActivity();
listAdapter = new AllEpisodesRecycleAdapter(mainActivity, itemAccess, showOnlyNewEpisodes());
listAdapter.setHasStableIds(true);
recyclerView.setAdapter(listAdapter);
emptyViewHandler.updateAdapter(listAdapter);
} }
private final AllEpisodesRecycleAdapter.ItemAccess itemAccess = new AllEpisodesRecycleAdapter.ItemAccess() { private final AllEpisodesRecycleAdapter.ItemAccess itemAccess = new AllEpisodesRecycleAdapter.ItemAccess() {
@Override @Override
public int getCount() { public int getCount() {
if (episodes != null) { return episodes.size();
return episodes.size();
}
return 0;
} }
@Override @Override
public FeedItem getItem(int position) { public FeedItem getItem(int position) {
if (episodes != null && 0 <= position && position < episodes.size()) { if (0 <= position && position < episodes.size()) {
return episodes.get(position); return episodes.get(position);
} }
return null; return null;
@ -390,11 +360,8 @@ public class AllEpisodesFragment extends Fragment {
@Override @Override
public LongList getItemsIds() { public LongList getItemsIds() {
if(episodes == null) {
return new LongList(0);
}
LongList ids = new LongList(episodes.size()); LongList ids = new LongList(episodes.size());
for(FeedItem episode : episodes) { for (FeedItem episode : episodes) {
ids.add(episode.getId()); ids.add(episode.getId());
} }
return ids; return ids;
@ -402,12 +369,11 @@ public class AllEpisodesFragment extends Fragment {
@Override @Override
public int getItemDownloadProgressPercent(FeedItem item) { public int getItemDownloadProgressPercent(FeedItem item) {
if (downloaderList != null) { for (Downloader downloader : downloaderList) {
for (Downloader downloader : downloaderList) { DownloadRequest downloadRequest = downloader.getDownloadRequest();
if (downloader.getDownloadRequest().getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA if (downloadRequest.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
&& downloader.getDownloadRequest().getFeedfileId() == item.getMedia().getId()) { && downloadRequest.getFeedfileId() == item.getMedia().getId()) {
return downloader.getDownloadRequest().getProgressPercent(); return downloadRequest.getProgressPercent();
}
} }
} }
return 0; return 0;
@ -421,11 +387,8 @@ public class AllEpisodesFragment extends Fragment {
@Override @Override
public LongList getQueueIds() { public LongList getQueueIds() {
LongList queueIds = new LongList(); LongList queueIds = new LongList();
if(episodes == null) { for (FeedItem item : episodes) {
return queueIds; if (item.isTagged(FeedItem.TAG_QUEUE)) {
}
for(FeedItem item : episodes) {
if(item.isTagged(FeedItem.TAG_QUEUE)) {
queueIds.add(item.getId()); queueIds.add(item.getId());
} }
} }
@ -437,12 +400,6 @@ public class AllEpisodesFragment extends Fragment {
@Subscribe(threadMode = ThreadMode.MAIN) @Subscribe(threadMode = ThreadMode.MAIN)
public void onEventMainThread(FeedItemEvent event) { public void onEventMainThread(FeedItemEvent event) {
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
if (episodes == null) {
return;
} else if (listAdapter == null) {
loadItems();
return;
}
for (FeedItem item : event.items) { for (FeedItem item : event.items) {
int pos = FeedItemUtil.indexOfItemWithId(episodes, item.getId()); int pos = FeedItemUtil.indexOfItemWithId(episodes, item.getId());
if (pos >= 0) { if (pos >= 0) {
@ -467,16 +424,12 @@ public class AllEpisodesFragment extends Fragment {
DownloaderUpdate update = event.update; DownloaderUpdate update = event.update;
downloaderList = update.downloaders; downloaderList = update.downloaders;
if (isMenuInvalidationAllowed && isUpdatingFeeds != update.feedIds.length > 0) { if (isMenuInvalidationAllowed && isUpdatingFeeds != update.feedIds.length > 0) {
getActivity().supportInvalidateOptionsMenu(); requireActivity().invalidateOptionsMenu();
}
if (listAdapter == null) {
loadItems();
return;
} }
if (update.mediaIds.length > 0) { if (update.mediaIds.length > 0) {
for(long mediaId : update.mediaIds) { for (long mediaId : update.mediaIds) {
int pos = FeedItemUtil.indexOfItemWithMediaId(episodes, mediaId); int pos = FeedItemUtil.indexOfItemWithMediaId(episodes, mediaId);
if(pos >= 0) { if (pos >= 0) {
listAdapter.notifyItemChanged(pos); listAdapter.notifyItemChanged(pos);
} }
} }
@ -489,35 +442,22 @@ public class AllEpisodesFragment extends Fragment {
if ((arg & EVENTS) != 0) { if ((arg & EVENTS) != 0) {
loadItems(); loadItems();
if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()) { if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()) {
getActivity().supportInvalidateOptionsMenu(); requireActivity().invalidateOptionsMenu();
} }
} }
} }
}; };
private void updateShowOnlyEpisodesListViewState() {
}
void loadItems() { void loadItems() {
if (disposable != null) { if (disposable != null) {
disposable.dispose(); disposable.dispose();
} }
if (viewsCreated && !itemsLoaded) {
recyclerView.setVisibility(View.GONE);
emptyView.hide();
progLoading.setVisibility(View.VISIBLE);
}
disposable = Observable.fromCallable(this::loadData) disposable = Observable.fromCallable(this::loadData)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(data -> { .subscribe(data -> {
recyclerView.setVisibility(View.VISIBLE);
progLoading.setVisibility(View.GONE); progLoading.setVisibility(View.GONE);
episodes = data; onFragmentLoaded(data);
itemsLoaded = true;
if (viewsCreated) {
onFragmentLoaded();
}
}, error -> Log.e(TAG, Log.getStackTraceString(error))); }, error -> Log.e(TAG, Log.getStackTraceString(error)));
} }
@ -540,7 +480,7 @@ public class AllEpisodesFragment extends Fragment {
DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId()); DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId());
final Handler h = new Handler(getActivity().getMainLooper()); final Handler h = new Handler(getActivity().getMainLooper());
final Runnable r = () -> { final Runnable r = () -> {
FeedMedia media = item.getMedia(); FeedMedia media = item.getMedia();
if (media != null && media.hasAlmostEnded() && UserPreferences.isAutoDelete()) { if (media != null && media.hasAlmostEnded() && UserPreferences.isAutoDelete()) {
DBWriter.deleteFeedMediaOfItem(getActivity(), media.getId()); DBWriter.deleteFeedMediaOfItem(getActivity(), media.getId());
@ -555,7 +495,6 @@ public class AllEpisodesFragment extends Fragment {
h.removeCallbacks(r); h.removeCallbacks(r);
}); });
snackbar.show(); snackbar.show();
h.postDelayed(r, (int)Math.ceil(snackbar.getDuration() * 1.05f)); h.postDelayed(r, (int) Math.ceil(snackbar.getDuration() * 1.05f));
} }
} }

View File

@ -1,7 +1,7 @@
package de.danoeh.antennapod.fragment; package de.danoeh.antennapod.fragment;
import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ListFragment; import android.support.v4.app.ListFragment;
import android.util.Log; import android.util.Log;
import android.view.Menu; import android.view.Menu;
@ -10,6 +10,7 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.ListView; import android.widget.ListView;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
@ -27,6 +28,9 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable; import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
import static de.danoeh.antennapod.dialog.EpisodesApplyActionFragment.ACTION_ADD_TO_QUEUE;
import static de.danoeh.antennapod.dialog.EpisodesApplyActionFragment.ACTION_DELETE;
/** /**
* Displays all running downloads and provides a button to delete them * Displays all running downloads and provides a button to delete them
*/ */
@ -38,24 +42,27 @@ public class CompletedDownloadsFragment extends ListFragment {
EventDistributor.DOWNLOADLOG_UPDATE | EventDistributor.DOWNLOADLOG_UPDATE |
EventDistributor.UNREAD_ITEMS_UPDATE; EventDistributor.UNREAD_ITEMS_UPDATE;
private List<FeedItem> items; private List<FeedItem> items = new ArrayList<>();
private DownloadedEpisodesListAdapter listAdapter; private DownloadedEpisodesListAdapter listAdapter;
private boolean viewCreated = false;
private Disposable disposable; private Disposable disposable;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onViewCreated(view, savedInstanceState);
setHasOptionsMenu(true); setHasOptionsMenu(true);
loadItems(); addVerticalPadding();
addEmptyView();
listAdapter = new DownloadedEpisodesListAdapter(getActivity(), itemAccess);
setListAdapter(listAdapter);
setListShown(false);
} }
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
EventDistributor.getInstance().register(contentUpdate); EventDistributor.getInstance().register(contentUpdate);
loadItems();
} }
@Override @Override
@ -68,104 +75,53 @@ public class CompletedDownloadsFragment extends ListFragment {
} }
@Override @Override
public void onDetach() { public void onListItemClick(ListView l, View v, int position, long id) {
super.onDetach(); super.onListItemClick(l, v, position, id);
if (disposable != null) { position -= l.getHeaderViewsCount();
disposable.dispose(); long[] ids = FeedItemUtil.getIds(items);
} ((MainActivity) requireActivity()).loadChildFragment(ItemFragment.newInstance(ids, position));
} }
@Override @Override
public void onDestroyView() { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onDestroyView(); super.onCreateOptionsMenu(menu, inflater);
listAdapter = null; inflater.inflate(R.menu.downloads_completed, menu);
viewCreated = false; menu.findItem(R.id.episode_actions).setVisible(items.size() > 0);
if (disposable != null) {
disposable.dispose();
}
} }
@Override @Override
public void onAttach(Context context) { public boolean onOptionsItemSelected(MenuItem item) {
super.onAttach(context); if (item.getItemId() == R.id.episode_actions) {
if (viewCreated && items != null) { ((MainActivity) requireActivity())
onFragmentLoaded(); .loadChildFragment(EpisodesApplyActionFragment.newInstance(items, ACTION_DELETE | ACTION_ADD_TO_QUEUE));
return true;
} }
return false;
} }
@Override private void addEmptyView() {
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// add padding
final ListView lv = getListView();
lv.setClipToPadding(false);
final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding);
lv.setPadding(0, vertPadding, 0, vertPadding);
viewCreated = true;
if (items != null && getActivity() != null) {
onFragmentLoaded();
}
EmptyViewHandler emptyView = new EmptyViewHandler(getActivity()); EmptyViewHandler emptyView = new EmptyViewHandler(getActivity());
emptyView.setTitle(R.string.no_comp_downloads_head_label); emptyView.setTitle(R.string.no_comp_downloads_head_label);
emptyView.setMessage(R.string.no_comp_downloads_label); emptyView.setMessage(R.string.no_comp_downloads_label);
emptyView.attachToListView(getListView()); emptyView.attachToListView(getListView());
} }
@Override private void addVerticalPadding() {
public void onListItemClick(ListView l, View v, int position, long id) { final ListView lv = getListView();
super.onListItemClick(l, v, position, id); lv.setClipToPadding(false);
position -= l.getHeaderViewsCount(); final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding);
long[] ids = FeedItemUtil.getIds(items); lv.setPadding(0, vertPadding, 0, vertPadding);
((MainActivity) getActivity()).loadChildFragment(ItemFragment.newInstance(ids, position));
}
private void onFragmentLoaded() {
if (listAdapter == null) {
listAdapter = new DownloadedEpisodesListAdapter(getActivity(), itemAccess);
setListAdapter(listAdapter);
}
setListShown(true);
listAdapter.notifyDataSetChanged();
getActivity().supportInvalidateOptionsMenu();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if(!isAdded()) {
return;
}
super.onCreateOptionsMenu(menu, inflater);
if(items != null) {
inflater.inflate(R.menu.downloads_completed, menu);
menu.findItem(R.id.episode_actions).setVisible(items.size() > 0);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.episode_actions:
EpisodesApplyActionFragment fragment = EpisodesApplyActionFragment
.newInstance(items, EpisodesApplyActionFragment.ACTION_DELETE | EpisodesApplyActionFragment.ACTION_ADD_TO_QUEUE);
((MainActivity) getActivity()).loadChildFragment(fragment);
return true;
default:
return false;
}
} }
private final DownloadedEpisodesListAdapter.ItemAccess itemAccess = new DownloadedEpisodesListAdapter.ItemAccess() { private final DownloadedEpisodesListAdapter.ItemAccess itemAccess = new DownloadedEpisodesListAdapter.ItemAccess() {
@Override @Override
public int getCount() { public int getCount() {
return (items != null) ? items.size() : 0; return items.size();
} }
@Override @Override
public FeedItem getItem(int position) { public FeedItem getItem(int position) {
if (items != null && 0 <= position && position < items.size()) { if (0 <= position && position < items.size()) {
return items.get(position); return items.get(position);
} else { } else {
return null; return null;
@ -174,7 +130,7 @@ public class CompletedDownloadsFragment extends ListFragment {
@Override @Override
public void onFeedItemSecondaryAction(FeedItem item) { public void onFeedItemSecondaryAction(FeedItem item) {
DBWriter.deleteFeedMediaOfItem(getActivity(), item.getMedia().getId()); DBWriter.deleteFeedMediaOfItem(requireActivity(), item.getMedia().getId());
} }
}; };
@ -191,18 +147,18 @@ public class CompletedDownloadsFragment extends ListFragment {
if (disposable != null) { if (disposable != null) {
disposable.dispose(); disposable.dispose();
} }
if (items == null && viewCreated) {
setListShown(false);
}
disposable = Observable.fromCallable(DBReader::getDownloadedItems) disposable = Observable.fromCallable(DBReader::getDownloadedItems)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> { .subscribe(result -> {
items = result; items = result;
if (viewCreated && getActivity() != null) { onItemsLoaded();
onFragmentLoaded(); }, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
} }
private void onItemsLoaded() {
setListShown(true);
listAdapter.notifyDataSetChanged();
requireActivity().invalidateOptionsMenu();
}
} }

View File

@ -14,6 +14,7 @@ import android.view.View;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
@ -37,18 +38,13 @@ public class DownloadLogFragment extends ListFragment {
private static final String TAG = "DownloadLogFragment"; private static final String TAG = "DownloadLogFragment";
private List<DownloadStatus> downloadLog; private List<DownloadStatus> downloadLog = new ArrayList<>();
private DownloadLogAdapter adapter; private DownloadLogAdapter adapter;
private boolean viewsCreated = false;
private boolean itemsLoaded = false;
private Disposable disposable; private Disposable disposable;
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
setHasOptionsMenu(true);
EventDistributor.getInstance().register(contentUpdate); EventDistributor.getInstance().register(contentUpdate);
loadItems(); loadItems();
} }
@ -57,7 +53,7 @@ public class DownloadLogFragment extends ListFragment {
public void onStop() { public void onStop() {
super.onStop(); super.onStop();
EventDistributor.getInstance().unregister(contentUpdate); EventDistributor.getInstance().unregister(contentUpdate);
if(disposable != null) { if (disposable != null) {
disposable.dispose(); disposable.dispose();
} }
} }
@ -65,6 +61,7 @@ public class DownloadLogFragment extends ListFragment {
@Override @Override
public void onViewCreated(View view, Bundle savedInstanceState) { public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
setHasOptionsMenu(true);
// add padding // add padding
final ListView lv = getListView(); final ListView lv = getListView();
@ -72,23 +69,16 @@ public class DownloadLogFragment extends ListFragment {
final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding); final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding);
lv.setPadding(0, vertPadding, 0, vertPadding); lv.setPadding(0, vertPadding, 0, vertPadding);
viewsCreated = true;
if (itemsLoaded) {
onFragmentLoaded();
}
EmptyViewHandler emptyView = new EmptyViewHandler(getActivity()); EmptyViewHandler emptyView = new EmptyViewHandler(getActivity());
emptyView.setTitle(R.string.no_log_downloads_head_label); emptyView.setTitle(R.string.no_log_downloads_head_label);
emptyView.setMessage(R.string.no_log_downloads_label); emptyView.setMessage(R.string.no_log_downloads_label);
emptyView.attachToListView(getListView()); emptyView.attachToListView(getListView());
adapter = new DownloadLogAdapter(getActivity(), itemAccess);
setListAdapter(adapter);
} }
private void onFragmentLoaded() { private void onFragmentLoaded() {
if (adapter == null) {
adapter = new DownloadLogAdapter(getActivity(), itemAccess);
setListAdapter(adapter);
}
setListShown(true); setListShown(true);
adapter.notifyDataSetChanged(); adapter.notifyDataSetChanged();
getActivity().supportInvalidateOptionsMenu(); getActivity().supportInvalidateOptionsMenu();
@ -129,12 +119,12 @@ public class DownloadLogFragment extends ListFragment {
@Override @Override
public int getCount() { public int getCount() {
return (downloadLog != null) ? downloadLog.size() : 0; return downloadLog.size();
} }
@Override @Override
public DownloadStatus getItem(int position) { public DownloadStatus getItem(int position) {
if (downloadLog != null && 0 <= position && position < downloadLog.size()) { if (0 <= position && position < downloadLog.size()) {
return downloadLog.get(position); return downloadLog.get(position);
} else { } else {
return null; return null;
@ -154,27 +144,23 @@ public class DownloadLogFragment extends ListFragment {
@Override @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if(!isAdded()) { if (!isAdded()) {
return; return;
} }
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);
if (itemsLoaded) { MenuItem clearHistory = menu.add(Menu.NONE, R.id.clear_history_item, Menu.CATEGORY_CONTAINER, R.string.clear_history_label);
MenuItem clearHistory = menu.add(Menu.NONE, R.id.clear_history_item, Menu.CATEGORY_CONTAINER, R.string.clear_history_label); MenuItemCompat.setShowAsAction(clearHistory, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
MenuItemCompat.setShowAsAction(clearHistory, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.content_discard});
TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.content_discard}); clearHistory.setIcon(drawables.getDrawable(0));
clearHistory.setIcon(drawables.getDrawable(0)); drawables.recycle();
drawables.recycle();
}
} }
@Override @Override
public void onPrepareOptionsMenu(Menu menu) { public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu); super.onPrepareOptionsMenu(menu);
if (itemsLoaded) { MenuItem menuItem = menu.findItem(R.id.clear_history_item);
MenuItem menuItem = menu.findItem(R.id.clear_history_item); if (menuItem != null) {
if(menuItem != null) { menuItem.setVisible(!downloadLog.isEmpty());
menuItem.setVisible(downloadLog != null && !downloadLog.isEmpty());
}
} }
} }
@ -194,7 +180,7 @@ public class DownloadLogFragment extends ListFragment {
} }
private void loadItems() { private void loadItems() {
if(disposable != null) { if (disposable != null) {
disposable.dispose(); disposable.dispose();
} }
disposable = Observable.fromCallable(DBReader::getDownloadLog) disposable = Observable.fromCallable(DBReader::getDownloadLog)
@ -203,12 +189,8 @@ public class DownloadLogFragment extends ListFragment {
.subscribe(result -> { .subscribe(result -> {
if (result != null) { if (result != null) {
downloadLog = result; downloadLog = result;
itemsLoaded = true; onFragmentLoaded();
if (viewsCreated) {
onFragmentLoaded();
}
} }
}, error -> Log.e(TAG, Log.getStackTraceString(error))); }, error -> Log.e(TAG, Log.getStackTraceString(error)));
} }
} }

View File

@ -1,6 +1,7 @@
package de.danoeh.antennapod.fragment; package de.danoeh.antennapod.fragment;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper; import android.support.v7.widget.helper.ItemTouchHelper;
@ -8,7 +9,8 @@ import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView;
import org.greenrobot.eventbus.Subscribe;
import java.util.List; import java.util.List;
@ -18,42 +20,36 @@ import de.danoeh.antennapod.core.event.FavoritesEvent;
import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.DBWriter;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
/** /**
* Like 'EpisodesFragment' except that it only shows favorite episodes and * Like 'EpisodesFragment' except that it only shows favorite episodes and
* supports swiping to remove from favorites. * supports swiping to remove from favorites.
*/ */
public class FavoriteEpisodesFragment extends AllEpisodesFragment { public class FavoriteEpisodesFragment extends AllEpisodesFragment {
private static final String TAG = "FavoriteEpisodesFrag"; private static final String TAG = "FavoriteEpisodesFrag";
private static final String PREF_NAME = "PrefFavoriteEpisodesFragment"; private static final String PREF_NAME = "PrefFavoriteEpisodesFragment";
@Override @Override
protected boolean showOnlyNewEpisodes() { return true; } protected boolean showOnlyNewEpisodes() {
return true;
}
@Override @Override
protected String getPrefName() { return PREF_NAME; } protected String getPrefName() {
return PREF_NAME;
}
@Subscribe @Subscribe
public void onEvent(FavoritesEvent event) { 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(); loadItems();
} }
@NonNull
@Override @Override
protected void resetViewState() { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.resetViewState(); View root = super.onCreateView(inflater, container, savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = super.onCreateViewHelper(inflater, container, savedInstanceState,
R.layout.all_episodes_fragment);
emptyView.setTitle(R.string.no_fav_episodes_head_label); emptyView.setTitle(R.string.no_fav_episodes_head_label);
emptyView.setMessage(R.string.no_fav_episodes_label); emptyView.setMessage(R.string.no_fav_episodes_label);
@ -65,8 +61,8 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment {
@Override @Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) { public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder)viewHolder; AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder) viewHolder;
Log.d(TAG, "remove(" + holder.getItemId() + ")"); Log.d(TAG, String.format("remove(%s)", holder.getItemId()));
if (disposable != null) { if (disposable != null) {
disposable.dispose(); disposable.dispose();
@ -75,8 +71,7 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment {
if (item != null) { if (item != null) {
DBWriter.removeFavoriteItem(item); DBWriter.removeFavoriteItem(item);
Snackbar snackbar = Snackbar.make(root, getString(R.string.removed_item), Snackbar snackbar = Snackbar.make(root, getString(R.string.removed_item), Snackbar.LENGTH_LONG);
Snackbar.LENGTH_LONG);
snackbar.setAction(getString(R.string.undo), v -> DBWriter.addFavoriteItem(item)); snackbar.setAction(getString(R.string.undo), v -> DBWriter.addFavoriteItem(item));
snackbar.show(); snackbar.show();
} }
@ -88,6 +83,7 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment {
return root; return root;
} }
@NonNull
@Override @Override
protected List<FeedItem> loadData() { protected List<FeedItem> loadData() {
return DBReader.getFavoriteItemsList(); return DBReader.getFavoriteItemsList();

View File

@ -36,6 +36,9 @@ import com.joanzapata.iconify.Iconify;
import com.joanzapata.iconify.widget.IconButton; import com.joanzapata.iconify.widget.IconButton;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.List; import java.util.List;
@ -71,9 +74,6 @@ import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable; import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
/** /**
* Displays information about a FeedItem and actions. * Displays information about a FeedItem and actions.
@ -266,7 +266,6 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
@Override @Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) { public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
load();
} }
@Override @Override
@ -274,6 +273,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
super.onStart(); super.onStart();
EventDistributor.getInstance().register(contentUpdate); EventDistributor.getInstance().register(contentUpdate);
EventBus.getDefault().register(this); EventBus.getDefault().register(this);
load();
} }
@Override @Override
@ -306,19 +306,20 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
@Override @Override
public boolean onSwipeLeftToRight() { public boolean onSwipeLeftToRight() {
Log.d(TAG, "onSwipeLeftToRight()"); return swipeFeedItem(-1);
feedItemPos = feedItemPos - 1;
if(feedItemPos < 0) {
feedItemPos = feedItems.length - 1;
}
load();
return true;
} }
@Override @Override
public boolean onSwipeRightToLeft() { public boolean onSwipeRightToLeft() {
Log.d(TAG, "onSwipeRightToLeft()"); return swipeFeedItem(+1);
feedItemPos = (feedItemPos + 1) % feedItems.length; }
private boolean swipeFeedItem(int position) {
Log.d(TAG, String.format("onSwipe() shift: %s", position));
feedItemPos = (feedItemPos + position) % feedItems.length;
if (feedItemPos < 0) {
feedItemPos = feedItems.length - 1;
}
load(); load();
return true; return true;
} }

View File

@ -30,6 +30,9 @@ import com.joanzapata.iconify.Iconify;
import com.joanzapata.iconify.widget.IconTextView; import com.joanzapata.iconify.widget.IconTextView;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.List; import java.util.List;
@ -71,9 +74,6 @@ import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable; import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
/** /**
* Displays a list of FeedItems. * Displays a list of FeedItems.
@ -96,8 +96,6 @@ public class ItemlistFragment extends ListFragment {
private long feedID; private long feedID;
private Feed feed; private Feed feed;
private boolean itemsLoaded = false;
private boolean viewsCreated = false;
private boolean headerCreated = false; private boolean headerCreated = false;
private List<Downloader> downloaderList; private List<Downloader> downloaderList;
@ -105,7 +103,7 @@ public class ItemlistFragment extends ListFragment {
private MoreContentListFooterUtil listFooter; private MoreContentListFooterUtil listFooter;
private boolean isUpdatingFeed; private boolean isUpdatingFeed;
private TextView txtvTitle; private TextView txtvTitle;
private IconTextView txtvFailure; private IconTextView txtvFailure;
private ImageView imgvBackground; private ImageView imgvBackground;
@ -146,9 +144,7 @@ public class ItemlistFragment extends ListFragment {
super.onStart(); super.onStart();
EventDistributor.getInstance().register(contentUpdate); EventDistributor.getInstance().register(contentUpdate);
EventBus.getDefault().register(this); EventBus.getDefault().register(this);
if (viewsCreated && itemsLoaded) { loadItems();
onFragmentLoaded();
}
} }
@Override @Override
@ -156,7 +152,6 @@ public class ItemlistFragment extends ListFragment {
super.onResume(); super.onResume();
((MainActivity)getActivity()).getSupportActionBar().setTitle(""); ((MainActivity)getActivity()).getSupportActionBar().setTitle("");
updateProgressBarVisibility(); updateProgressBarVisibility();
loadItems();
} }
@Override @Override
@ -177,7 +172,6 @@ public class ItemlistFragment extends ListFragment {
private void resetViewState() { private void resetViewState() {
adapter = null; adapter = null;
viewsCreated = false;
listFooter = null; listFooter = null;
} }
@ -190,45 +184,43 @@ public class ItemlistFragment extends ListFragment {
@Override @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if(!isAdded()) { if (!isAdded()) {
return; return;
} }
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);
if (itemsLoaded) { FeedMenuHandler.onCreateOptionsMenu(inflater, menu);
FeedMenuHandler.onCreateOptionsMenu(inflater, menu);
MenuItem searchItem = menu.findItem(R.id.action_search); MenuItem searchItem = menu.findItem(R.id.action_search);
final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem); final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem);
MenuItemUtils.adjustTextColor(getActivity(), sv); MenuItemUtils.adjustTextColor(getActivity(), sv);
sv.setQueryHint(getString(R.string.search_hint)); sv.setQueryHint(getString(R.string.search_hint));
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override @Override
public boolean onQueryTextSubmit(String s) { public boolean onQueryTextSubmit(String s) {
sv.clearFocus(); sv.clearFocus();
if (itemsLoaded) { if (feed != null) {
((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance(s, feed.getId())); ((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance(s, feed.getId()));
}
return true;
} }
return true;
@Override
public boolean onQueryTextChange(String s) {
return false;
}
});
if(feed == null || feed.getLink() == null) {
menu.findItem(R.id.share_link_item).setVisible(false);
menu.findItem(R.id.visit_website_item).setVisible(false);
} }
isUpdatingFeed = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker); @Override
public boolean onQueryTextChange(String s) {
return false;
}
});
if (feed == null || feed.getLink() == null) {
menu.findItem(R.id.share_link_item).setVisible(false);
menu.findItem(R.id.visit_website_item).setVisible(false);
} }
isUpdatingFeed = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
} }
@Override @Override
public void onPrepareOptionsMenu(Menu menu) { public void onPrepareOptionsMenu(Menu menu) {
if (itemsLoaded) { if (feed != null) {
FeedMenuHandler.onPrepareOptionsMenu(menu, feed); FeedMenuHandler.onPrepareOptionsMenu(menu, feed);
} }
} }
@ -341,11 +333,6 @@ public class ItemlistFragment extends ListFragment {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
registerForContextMenu(getListView()); registerForContextMenu(getListView());
viewsCreated = true;
if (itemsLoaded) {
onFragmentLoaded();
}
} }
@Override @Override
@ -503,7 +490,7 @@ public class ItemlistFragment extends ListFragment {
butShowInfo.setOnClickListener(v -> showFeedInfo()); butShowInfo.setOnClickListener(v -> showFeedInfo());
imgvCover.setOnClickListener(v -> showFeedInfo()); imgvCover.setOnClickListener(v -> showFeedInfo());
butShowSettings.setOnClickListener(v -> { butShowSettings.setOnClickListener(v -> {
if (viewsCreated && itemsLoaded) { if (feed != null) {
Intent startIntent = new Intent(getActivity(), FeedSettingsActivity.class); Intent startIntent = new Intent(getActivity(), FeedSettingsActivity.class);
startIntent.putExtra(FeedSettingsActivity.EXTRA_FEED_ID, startIntent.putExtra(FeedSettingsActivity.EXTRA_FEED_ID,
feed.getId()); feed.getId());
@ -514,7 +501,7 @@ public class ItemlistFragment extends ListFragment {
} }
private void showFeedInfo() { private void showFeedInfo() {
if (viewsCreated && itemsLoaded) { if (feed != null) {
Intent startIntent = new Intent(getActivity(), FeedInfoActivity.class); Intent startIntent = new Intent(getActivity(), FeedInfoActivity.class);
startIntent.putExtra(FeedInfoActivity.EXTRA_FEED_ID, startIntent.putExtra(FeedInfoActivity.EXTRA_FEED_ID,
feed.getId()); feed.getId());
@ -624,10 +611,7 @@ public class ItemlistFragment extends ListFragment {
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> { .subscribe(result -> {
feed = result.orElse(null); feed = result.orElse(null);
itemsLoaded = true; onFragmentLoaded();
if (viewsCreated) {
onFragmentLoaded();
}
}, error -> Log.e(TAG, Log.getStackTraceString(error))); }, error -> Log.e(TAG, Log.getStackTraceString(error)));
} }

View File

@ -1,40 +1,37 @@
package de.danoeh.antennapod.fragment; package de.danoeh.antennapod.fragment;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper; import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List; import java.util.List;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter; import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter;
import de.danoeh.antennapod.core.event.FeedItemEvent;
import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.util.FeedItemUtil;
/** /**
* Like 'EpisodesFragment' except that it only shows new episodes and * Like 'EpisodesFragment' except that it only shows new episodes and
* supports swiping to mark as read. * supports swiping to mark as read.
*/ */
public class NewEpisodesFragment extends AllEpisodesFragment { public class NewEpisodesFragment extends AllEpisodesFragment {
public static final String TAG = "NewEpisodesFragment"; public static final String TAG = "NewEpisodesFragment";
private static final String PREF_NAME = "PrefNewEpisodesFragment"; private static final String PREF_NAME = "PrefNewEpisodesFragment";
@Override
protected boolean showOnlyNewEpisodes() { return true; }
@Override @Override
protected String getPrefName() { return PREF_NAME; } protected boolean showOnlyNewEpisodes() {
return true;
}
@Override @Override
protected void resetViewState() { protected String getPrefName() {
super.resetViewState(); return PREF_NAME;
} }
@Override @Override
@ -42,10 +39,10 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
return item.isNew(); return item.isNew();
} }
@NonNull
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = super.onCreateViewHelper(inflater, container, savedInstanceState, View root = super.onCreateView(inflater, container, savedInstanceState);
R.layout.all_episodes_fragment);
emptyView.setTitle(R.string.no_new_episodes_head_label); emptyView.setTitle(R.string.no_new_episodes_head_label);
emptyView.setMessage(R.string.no_new_episodes_label); emptyView.setMessage(R.string.no_new_episodes_label);
@ -57,7 +54,7 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
@Override @Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) { public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder)viewHolder; AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder) viewHolder;
markItemAsSeenWithUndo(holder.getFeedItem()); markItemAsSeenWithUndo(holder.getFeedItem());
} }
@ -75,6 +72,7 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
super.onSelectedChanged(viewHolder, actionState); super.onSelectedChanged(viewHolder, actionState);
} }
@Override @Override
public void clearView(RecyclerView recyclerView, public void clearView(RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder) { RecyclerView.ViewHolder viewHolder) {
@ -94,9 +92,9 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
return root; return root;
} }
@NonNull
@Override @Override
protected List<FeedItem> loadData() { protected List<FeedItem> loadData() {
return DBReader.getNewItemsList(); return DBReader.getNewItemsList();
} }
} }

View File

@ -1,6 +1,5 @@
package de.danoeh.antennapod.fragment; package de.danoeh.antennapod.fragment;
import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
@ -13,6 +12,10 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.ListView; import android.widget.ListView;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import java.util.List; import java.util.List;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
@ -34,9 +37,6 @@ import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable; import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
public class PlaybackHistoryFragment extends ListFragment { public class PlaybackHistoryFragment extends ListFragment {
@ -47,22 +47,9 @@ public class PlaybackHistoryFragment extends ListFragment {
private List<FeedItem> playbackHistory; private List<FeedItem> playbackHistory;
private FeedItemlistAdapter adapter; private FeedItemlistAdapter adapter;
private boolean itemsLoaded = false;
private boolean viewsCreated = false;
private List<Downloader> downloaderList; private List<Downloader> downloaderList;
private Disposable disposable; private Disposable disposable;
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (viewsCreated && itemsLoaded) {
onFragmentLoaded();
}
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -80,16 +67,16 @@ public class PlaybackHistoryFragment extends ListFragment {
final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding); final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding);
lv.setPadding(0, vertPadding, 0, vertPadding); lv.setPadding(0, vertPadding, 0, vertPadding);
viewsCreated = true;
if (itemsLoaded) {
onFragmentLoaded();
}
EmptyViewHandler emptyView = new EmptyViewHandler(getActivity()); EmptyViewHandler emptyView = new EmptyViewHandler(getActivity());
emptyView.setTitle(R.string.no_history_head_label); emptyView.setTitle(R.string.no_history_head_label);
emptyView.setMessage(R.string.no_history_label); emptyView.setMessage(R.string.no_history_label);
emptyView.attachToListView(getListView()); emptyView.attachToListView(getListView());
// played items shoudln't be transparent for this fragment since, *all* items
// in this fragment will, by definition, be played. So it serves no purpose and can make
// it harder to read.
adapter = new FeedItemlistAdapter(getActivity(), itemAccess, true, false);
setListAdapter(adapter);
} }
@Override @Override
@ -105,34 +92,17 @@ public class PlaybackHistoryFragment extends ListFragment {
super.onStop(); super.onStop();
EventBus.getDefault().unregister(this); EventBus.getDefault().unregister(this);
EventDistributor.getInstance().unregister(contentUpdate); EventDistributor.getInstance().unregister(contentUpdate);
if(disposable != null) { if (disposable != null) {
disposable.dispose(); disposable.dispose();
} }
} }
@Override
public void onDetach() {
super.onDetach();
if(disposable != null) {
disposable.dispose();
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
adapter = null;
viewsCreated = false;
}
@Subscribe(sticky = true) @Subscribe(sticky = true)
public void onEvent(DownloadEvent event) { public void onEvent(DownloadEvent event) {
Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]"); Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
DownloaderUpdate update = event.update; DownloaderUpdate update = event.update;
downloaderList = update.downloaders; downloaderList = update.downloaders;
if (adapter != null) { adapter.notifyDataSetChanged();
adapter.notifyDataSetChanged();
}
} }
@Override @Override
@ -145,27 +115,23 @@ public class PlaybackHistoryFragment extends ListFragment {
@Override @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if(!isAdded()) { if (!isAdded()) {
return; return;
} }
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);
if (itemsLoaded) { MenuItem clearHistory = menu.add(Menu.NONE, R.id.clear_history_item, Menu.CATEGORY_CONTAINER, R.string.clear_history_label);
MenuItem clearHistory = menu.add(Menu.NONE, R.id.clear_history_item, Menu.CATEGORY_CONTAINER, R.string.clear_history_label); MenuItemCompat.setShowAsAction(clearHistory, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
MenuItemCompat.setShowAsAction(clearHistory, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.content_discard});
TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.content_discard}); clearHistory.setIcon(drawables.getDrawable(0));
clearHistory.setIcon(drawables.getDrawable(0)); drawables.recycle();
drawables.recycle();
}
} }
@Override @Override
public void onPrepareOptionsMenu(Menu menu) { public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu); super.onPrepareOptionsMenu(menu);
if (itemsLoaded) { MenuItem menuItem = menu.findItem(R.id.clear_history_item);
MenuItem menuItem = menu.findItem(R.id.clear_history_item); if (menuItem != null) {
if (menuItem != null) { menuItem.setVisible(playbackHistory != null && !playbackHistory.isEmpty());
menuItem.setVisible(playbackHistory != null && !playbackHistory.isEmpty());
}
} }
} }
@ -211,14 +177,6 @@ public class PlaybackHistoryFragment extends ListFragment {
}; };
private void onFragmentLoaded() { private void onFragmentLoaded() {
if (adapter == null) {
// played items shoudln't be transparent for this fragment since, *all* items
// in this fragment will, by definition, be played. So it serves no purpose and can make
// it harder to read.
adapter = new FeedItemlistAdapter(getActivity(), itemAccess, true, false);
setListAdapter(adapter);
}
setListShown(true);
adapter.notifyDataSetChanged(); adapter.notifyDataSetChanged();
getActivity().supportInvalidateOptionsMenu(); getActivity().supportInvalidateOptionsMenu();
} }
@ -277,10 +235,7 @@ public class PlaybackHistoryFragment extends ListFragment {
.subscribe(result -> { .subscribe(result -> {
if (result != null) { if (result != null) {
playbackHistory = result; playbackHistory = result;
itemsLoaded = true; onFragmentLoaded();
if (viewsCreated) {
onFragmentLoaded();
}
} }
}, error -> Log.e(TAG, Log.getStackTraceString(error))); }, error -> Log.e(TAG, Log.getStackTraceString(error)));
} }
@ -291,5 +246,4 @@ public class PlaybackHistoryFragment extends ListFragment {
DBReader.loadAdditionalFeedItemListData(history); DBReader.loadAdditionalFeedItemListData(history);
return history; return history;
} }
} }

View File

@ -7,6 +7,10 @@ import android.view.View;
import android.widget.ListView; import android.widget.ListView;
import android.widget.Toast; import android.widget.Toast;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
@ -21,8 +25,6 @@ import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.view.EmptyViewHandler; import de.danoeh.antennapod.view.EmptyViewHandler;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
/** /**
* Displays all running downloads and provides actions to cancel them * Displays all running downloads and provides actions to cancel them
@ -32,7 +34,7 @@ public class RunningDownloadsFragment extends ListFragment {
private static final String TAG = "RunningDownloadsFrag"; private static final String TAG = "RunningDownloadsFrag";
private DownloadlistAdapter adapter; private DownloadlistAdapter adapter;
private List<Downloader> downloaderList; private List<Downloader> downloaderList = new ArrayList<>();
@Override @Override
public void onViewCreated(View view, Bundle savedInstanceState) { public void onViewCreated(View view, Bundle savedInstanceState) {
@ -70,7 +72,6 @@ public class RunningDownloadsFragment extends ListFragment {
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
setListAdapter(null); setListAdapter(null);
adapter = null;
} }
@Subscribe(sticky = true) @Subscribe(sticky = true)
@ -78,21 +79,18 @@ public class RunningDownloadsFragment extends ListFragment {
Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]"); Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
DownloaderUpdate update = event.update; DownloaderUpdate update = event.update;
downloaderList = update.downloaders; downloaderList = update.downloaders;
if (adapter != null) { adapter.notifyDataSetChanged();
adapter.notifyDataSetChanged();
}
} }
private final DownloadlistAdapter.ItemAccess itemAccess = new DownloadlistAdapter.ItemAccess() { private final DownloadlistAdapter.ItemAccess itemAccess = new DownloadlistAdapter.ItemAccess() {
@Override @Override
public int getCount() { public int getCount() {
return (downloaderList != null) ? downloaderList.size() : 0; return downloaderList.size();
} }
@Override @Override
public Downloader getItem(int position) { public Downloader getItem(int position) {
if (downloaderList != null && 0 <= position && position < downloaderList.size()) { if (0 <= position && position < downloaderList.size()) {
return downloaderList.get(position); return downloaderList.get(position);
} else { } else {
return null; return null;

View File

@ -14,6 +14,7 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.ListView; import android.widget.ListView;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
@ -40,11 +41,7 @@ public class SearchFragment extends ListFragment {
private static final String ARG_FEED = "feed"; private static final String ARG_FEED = "feed";
private SearchlistAdapter searchAdapter; private SearchlistAdapter searchAdapter;
private List<SearchResult> searchResults; private List<SearchResult> searchResults = new ArrayList<>();
private boolean viewCreated = false;
private boolean itemsLoaded = false;
private Disposable disposable; private Disposable disposable;
/** /**
@ -74,13 +71,13 @@ public class SearchFragment extends ListFragment {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setRetainInstance(true); setRetainInstance(true);
setHasOptionsMenu(true); setHasOptionsMenu(true);
search();
} }
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
EventDistributor.getInstance().register(contentUpdate); EventDistributor.getInstance().register(contentUpdate);
search();
} }
@Override @Override
@ -92,21 +89,6 @@ public class SearchFragment extends ListFragment {
EventDistributor.getInstance().unregister(contentUpdate); EventDistributor.getInstance().unregister(contentUpdate);
} }
@Override
public void onDetach() {
super.onDetach();
if(disposable != null) {
disposable.dispose();
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
searchAdapter = null;
viewCreated = false;
}
@Override @Override
public void onViewCreated(View view, Bundle savedInstanceState) { public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
@ -118,10 +100,9 @@ public class SearchFragment extends ListFragment {
lv.setPadding(0, vertPadding, 0, vertPadding); lv.setPadding(0, vertPadding, 0, vertPadding);
((AppCompatActivity) getActivity()).getSupportActionBar().setTitle(R.string.search_label); ((AppCompatActivity) getActivity()).getSupportActionBar().setTitle(R.string.search_label);
viewCreated = true;
if (itemsLoaded) { searchAdapter = new SearchlistAdapter(getActivity(), itemAccess);
onFragmentLoaded(); setListAdapter(searchAdapter);
}
} }
@Override @Override
@ -142,28 +123,26 @@ public class SearchFragment extends ListFragment {
@Override @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);
if (itemsLoaded) { MenuItem item = menu.add(Menu.NONE, R.id.search_item, Menu.NONE, R.string.search_label);
MenuItem item = menu.add(Menu.NONE, R.id.search_item, Menu.NONE, R.string.search_label); MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); final SearchView sv = new SearchView(getActivity());
final SearchView sv = new SearchView(getActivity()); sv.setQueryHint(getString(R.string.search_hint));
sv.setQueryHint(getString(R.string.search_hint)); sv.setQuery(getArguments().getString(ARG_QUERY), false);
sv.setQuery(getArguments().getString(ARG_QUERY), false); sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override
@Override public boolean onQueryTextSubmit(String s) {
public boolean onQueryTextSubmit(String s) { sv.clearFocus();
getArguments().putString(ARG_QUERY, s); getArguments().putString(ARG_QUERY, s);
itemsLoaded = false; search();
search(); return true;
return true; }
}
@Override @Override
public boolean onQueryTextChange(String s) { public boolean onQueryTextChange(String s) {
return false; return false;
} }
}); });
MenuItemCompat.setActionView(item, sv); MenuItemCompat.setActionView(item, sv);
}
} }
private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() { private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@ -176,14 +155,9 @@ public class SearchFragment extends ListFragment {
} }
}; };
private void onFragmentLoaded() { private void onSearchResults(List<SearchResult> results) {
if (searchAdapter == null) { searchResults = results;
searchAdapter = new SearchlistAdapter(getActivity(), itemAccess);
setListAdapter(searchAdapter);
}
searchAdapter.notifyDataSetChanged(); searchAdapter.notifyDataSetChanged();
setListShown(true);
String query = getArguments().getString(ARG_QUERY); String query = getArguments().getString(ARG_QUERY);
setEmptyText(getString(R.string.no_results_for_query, query)); setEmptyText(getString(R.string.no_results_for_query, query));
} }
@ -191,12 +165,12 @@ public class SearchFragment extends ListFragment {
private final SearchlistAdapter.ItemAccess itemAccess = new SearchlistAdapter.ItemAccess() { private final SearchlistAdapter.ItemAccess itemAccess = new SearchlistAdapter.ItemAccess() {
@Override @Override
public int getCount() { public int getCount() {
return (searchResults != null) ? searchResults.size() : 0; return searchResults.size();
} }
@Override @Override
public SearchResult getItem(int position) { public SearchResult getItem(int position) {
if (searchResults != null && 0 <= position && position < searchResults.size()) { if (0 <= position && position < searchResults.size()) {
return searchResults.get(position); return searchResults.get(position);
} else { } else {
return null; return null;
@ -204,24 +178,14 @@ public class SearchFragment extends ListFragment {
} }
}; };
private void search() { private void search() {
if(disposable != null) { if(disposable != null) {
disposable.dispose(); disposable.dispose();
} }
if (viewCreated && !itemsLoaded) {
setListShown(false);
}
disposable = Observable.fromCallable(this::performSearch) disposable = Observable.fromCallable(this::performSearch)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> { .subscribe(this::onSearchResults, error -> Log.e(TAG, Log.getStackTraceString(error)));
itemsLoaded = true;
searchResults = result;
if (viewCreated) {
onFragmentLoaded();
}
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
} }
@NonNull @NonNull
@ -232,5 +196,4 @@ public class SearchFragment extends ListFragment {
Context context = getActivity(); Context context = getActivity();
return FeedSearcher.performSearch(context, query, feed); return FeedSearcher.performSearch(context, query, feed);
} }
} }

View File

@ -1,9 +1,11 @@
package de.danoeh.antennapod.fragment; package de.danoeh.antennapod.fragment;
import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.StringRes;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.util.Log; import android.util.Log;
import android.view.ContextMenu; import android.view.ContextMenu;
@ -16,6 +18,8 @@ import android.view.ViewGroup;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.GridView; import android.widget.GridView;
import java.util.concurrent.Callable;
import de.danoeh.antennapod.R; import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.SubscriptionsAdapter; import de.danoeh.antennapod.adapter.SubscriptionsAdapter;
@ -56,16 +60,13 @@ public class SubscriptionFragment extends Fragment {
private Disposable disposable; private Disposable disposable;
private SharedPreferences prefs; private SharedPreferences prefs;
public SubscriptionFragment() {
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setRetainInstance(true); setRetainInstance(true);
setHasOptionsMenu(true); setHasOptionsMenu(true);
prefs = getActivity().getSharedPreferences(PREFS, Context.MODE_PRIVATE); prefs = requireActivity().getSharedPreferences(PREFS, Context.MODE_PRIVATE);
} }
@Override @Override
@ -123,23 +124,25 @@ public class SubscriptionFragment extends Fragment {
public void onActivityCreated(Bundle savedInstanceState) { public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
subscriptionAdapter = new SubscriptionsAdapter((MainActivity)getActivity(), itemAccess); subscriptionAdapter = new SubscriptionsAdapter((MainActivity)getActivity(), itemAccess);
subscriptionGridLayout.setAdapter(subscriptionAdapter); subscriptionGridLayout.setAdapter(subscriptionAdapter);
loadSubscriptions();
subscriptionGridLayout.setOnItemClickListener(subscriptionAdapter); subscriptionGridLayout.setOnItemClickListener(subscriptionAdapter);
if (getActivity() instanceof MainActivity) { if (getActivity() instanceof MainActivity) {
((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.subscriptions_label); ((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.subscriptions_label);
} }
EventDistributor.getInstance().register(contentUpdate);
} }
@Override @Override
public void onDestroy() { public void onStart() {
super.onDestroy(); super.onStart();
EventDistributor.getInstance().register(contentUpdate);
loadSubscriptions();
}
@Override
public void onStop() {
super.onStop();
EventDistributor.getInstance().unregister(contentUpdate);
if(disposable != null) { if(disposable != null) {
disposable.dispose(); disposable.dispose();
} }
@ -172,7 +175,7 @@ public class SubscriptionFragment extends Fragment {
Feed feed = (Feed)selectedObject; Feed feed = (Feed)selectedObject;
MenuInflater inflater = getActivity().getMenuInflater(); MenuInflater inflater = requireActivity().getMenuInflater();
inflater.inflate(R.menu.nav_feed_context, menu); inflater.inflate(R.menu.nav_feed_context, menu);
menu.setHeaderTitle(feed.getTitle()); menu.setHeaderTitle(feed.getTitle());
@ -182,7 +185,6 @@ public class SubscriptionFragment extends Fragment {
@Override @Override
public boolean onContextItemSelected(MenuItem item) { public boolean onContextItemSelected(MenuItem item) {
final int position = mPosition; final int position = mPosition;
mPosition = -1; // reset mPosition = -1; // reset
if(position < 0) { if(position < 0) {
@ -198,83 +200,72 @@ public class SubscriptionFragment extends Fragment {
Feed feed = (Feed)selectedObject; Feed feed = (Feed)selectedObject;
switch(item.getItemId()) { switch(item.getItemId()) {
case R.id.mark_all_seen_item: case R.id.mark_all_seen_item:
ConfirmationDialog markAllSeenConfirmationDialog = new ConfirmationDialog(getActivity(), displayConfirmationDialog(
R.string.mark_all_seen_label, R.string.mark_all_seen_label,
R.string.mark_all_seen_confirmation_msg) { R.string.mark_all_seen_confirmation_msg,
() -> DBWriter.markFeedSeen(feed.getId()));
@Override
public void onConfirmButtonPressed(DialogInterface dialog) {
dialog.dismiss();
Observable.fromCallable(() -> DBWriter.markFeedSeen(feed.getId()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> loadSubscriptions(),
error -> Log.e(TAG, Log.getStackTraceString(error)));
}
};
markAllSeenConfirmationDialog.createNewDialog().show();
return true; return true;
case R.id.mark_all_read_item: case R.id.mark_all_read_item:
ConfirmationDialog markAllReadConfirmationDialog = new ConfirmationDialog(getActivity(), displayConfirmationDialog(
R.string.mark_all_read_label, R.string.mark_all_read_label,
R.string.mark_all_read_confirmation_msg) { R.string.mark_all_read_confirmation_msg,
() -> DBWriter.markFeedRead(feed.getId()));
@Override
public void onConfirmButtonPressed(DialogInterface dialog) {
dialog.dismiss();
Observable.fromCallable(() -> DBWriter.markFeedRead(feed.getId()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> loadSubscriptions(),
error -> Log.e(TAG, Log.getStackTraceString(error)));
}
};
markAllReadConfirmationDialog.createNewDialog().show();
return true; return true;
case R.id.rename_item: case R.id.rename_item:
new RenameFeedDialog(getActivity(), feed).show(); new RenameFeedDialog(getActivity(), feed).show();
return true; return true;
case R.id.remove_item: case R.id.remove_item:
final FeedRemover remover = new FeedRemover(getContext(), feed) { displayRemoveFeedDialog(feed);
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
loadSubscriptions();
}
};
ConfirmationDialog conDialog = new ConfirmationDialog(getContext(),
R.string.remove_feed_label,
getString(R.string.feed_delete_confirmation_msg, feed.getTitle())) {
@Override
public void onConfirmButtonPressed(
DialogInterface dialog) {
dialog.dismiss();
long mediaId = PlaybackPreferences.getCurrentlyPlayingFeedMediaId();
if (mediaId > 0 &&
FeedItemUtil.indexOfItemWithMediaId(feed.getItems(), mediaId) >= 0) {
Log.d(TAG, "Currently playing episode is about to be deleted, skipping");
remover.skipOnCompletion = true;
int playerStatus = PlaybackPreferences.getCurrentPlayerStatus();
if(playerStatus == PlaybackPreferences.PLAYER_STATUS_PLAYING) {
IntentUtils.sendLocalBroadcast(getContext(), PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE);
}
}
remover.executeAsync();
}
};
conDialog.createNewDialog().show();
return true; return true;
default: default:
return super.onContextItemSelected(item); return super.onContextItemSelected(item);
} }
} }
@Override private void displayRemoveFeedDialog(Feed feed) {
public void onResume() { final FeedRemover remover = new FeedRemover(getContext(), feed) {
super.onResume(); @Override
loadSubscriptions(); protected void onPostExecute(Void result) {
super.onPostExecute(result);
loadSubscriptions();
}
};
String message = getString(R.string.feed_delete_confirmation_msg, feed.getTitle());
ConfirmationDialog dialog = new ConfirmationDialog(getContext(), R.string.remove_feed_label, message) {
@Override
public void onConfirmButtonPressed(DialogInterface clickedDialog) {
clickedDialog.dismiss();
long mediaId = PlaybackPreferences.getCurrentlyPlayingFeedMediaId();
if (mediaId > 0 && FeedItemUtil.indexOfItemWithMediaId(feed.getItems(), mediaId) >= 0) {
Log.d(TAG, "Currently playing episode is about to be deleted, skipping");
remover.skipOnCompletion = true;
int playerStatus = PlaybackPreferences.getCurrentPlayerStatus();
if(playerStatus == PlaybackPreferences.PLAYER_STATUS_PLAYING) {
IntentUtils.sendLocalBroadcast(getContext(), PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE);
}
}
remover.executeAsync();
}
};
dialog.createNewDialog().show();
}
private <T> void displayConfirmationDialog(@StringRes int title, @StringRes int message, Callable<? extends T> task) {
ConfirmationDialog dialog = new ConfirmationDialog(getActivity(), title, message) {
@Override
@SuppressLint("CheckResult")
public void onConfirmButtonPressed(DialogInterface clickedDialog) {
clickedDialog.dismiss();
Observable.fromCallable(task)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> loadSubscriptions(),
error -> Log.e(TAG, Log.getStackTraceString(error)));
}
};
dialog.createNewDialog().show();
} }
private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() { private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {

View File

@ -1,5 +1,7 @@
package de.danoeh.antennapod.core.event; package de.danoeh.antennapod.core.event;
import android.support.annotation.NonNull;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -11,6 +13,7 @@ import de.danoeh.antennapod.core.util.LongList;
public class DownloaderUpdate { public class DownloaderUpdate {
/* Downloaders that are currently running */ /* Downloaders that are currently running */
@NonNull
public final List<Downloader> downloaders; public final List<Downloader> downloaders;
/** /**
@ -25,7 +28,7 @@ public class DownloaderUpdate {
*/ */
public final long[] mediaIds; public final long[] mediaIds;
public DownloaderUpdate(List<Downloader> downloaders) { DownloaderUpdate(@NonNull List<Downloader> downloaders) {
this.downloaders = downloaders; this.downloaders = downloaders;
LongList feedIds1 = new LongList(), mediaIds1 = new LongList(); LongList feedIds1 = new LongList(), mediaIds1 = new LongList();
for(Downloader d1 : downloaders) { for(Downloader d1 : downloaders) {