diff options
12 files changed, 364 insertions, 599 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java index cdbb23985..0b38fe18a 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java @@ -21,11 +21,15 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ProgressBar; -import android.widget.TextView; import android.widget.Toast; 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 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.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; @@ -50,15 +55,11 @@ import de.danoeh.antennapod.core.util.FeedItemUtil; import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; import de.danoeh.antennapod.menuhandler.MenuItemUtils; - import de.danoeh.antennapod.view.EmptyViewHandler; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; 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 @@ -81,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; @@ -93,29 +93,26 @@ public class AllEpisodesFragment extends Fragment { Disposable disposable; private LinearLayoutManager layoutManager; - boolean showOnlyNewEpisodes() { return false; } - String getPrefName() { return DEFAULT_PREF_NAME; } + boolean showOnlyNewEpisodes() { + return false; + } - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setHasOptionsMenu(true); + String getPrefName() { + return DEFAULT_PREF_NAME; } @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); } @@ -136,17 +133,11 @@ public class AllEpisodesFragment extends Fragment { } } - @Override - public void onDestroyView() { - super.onDestroyView(); - resetViewState(); - } - private void saveScrollPosition() { int firstItem = layoutManager.findFirstVisibleItemPosition(); View firstItemView = layoutManager.findViewByPosition(firstItem); float topOffset; - if(firstItemView == null) { + if (firstItemView == null) { topOffset = 0; } else { topOffset = firstItemView.getTop(); @@ -173,43 +164,35 @@ public class AllEpisodesFragment extends Fragment { } } - void resetViewState() { - viewsCreated = false; - listAdapter = null; - } - - private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker = () -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds(); @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - if(!isAdded()) { + if (!isAdded()) { return; } super.onCreateOptionsMenu(menu, inflater); - if (itemsLoaded) { - 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; - } + 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) 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 @@ -217,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()); + if (markAllSeen != null) { + markAllSeen.setVisible(showOnlyNewEpisodes() && !episodes.isEmpty()); } } @@ -278,14 +261,14 @@ public class AllEpisodesFragment extends Fragment { if (!getUserVisibleHint()) { return false; } - if(!isVisible()) { + if (!isVisible()) { 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 } - 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); } @@ -304,85 +287,72 @@ 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); - - recyclerView = root.findViewById(android.R.id.list); - RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator(); - if (animator instanceof SimpleItemAnimator) { - ((SimpleItemAnimator) animator).setSupportsChangeAnimations(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); - progLoading = root.findViewById(R.id.progLoading); - - if (!itemsLoaded) { - progLoading.setVisibility(View.VISIBLE); + RecyclerView.ItemAnimator animator = recyclerView.getItemAnimator(); + if (animator instanceof SimpleItemAnimator) { + ((SimpleItemAnimator) animator).setSupportsChangeAnimations(false); } - viewsCreated = true; - - if (itemsLoaded) { - onFragmentLoaded(); - } + progLoading = root.findViewById(R.id.progLoading); + 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); + createRecycleAdapter(recyclerView, emptyView); + emptyView.hide(); + 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); - } - recyclerView.setVisibility(View.VISIBLE); - listAdapter.notifyDataSetChanged(); - } else { - listAdapter = null; - recyclerView.setVisibility(View.GONE); - emptyView.updateAdapter(listAdapter); + private void onFragmentLoaded(List<FeedItem> episodes) { + this.episodes = episodes; + listAdapter.notifyDataSetChanged(); + + if (episodes.size() == 0) { + createRecycleAdapter(recyclerView, emptyView); } 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(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() { @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; @@ -390,11 +360,8 @@ 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) { + for (FeedItem episode : episodes) { ids.add(episode.getId()); } return ids; @@ -402,12 +369,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; @@ -421,11 +387,8 @@ 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)) { + for (FeedItem item : episodes) { + if (item.isTagged(FeedItem.TAG_QUEUE)) { queueIds.add(item.getId()); } } @@ -437,12 +400,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) { @@ -467,16 +424,12 @@ 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) { + for (long mediaId : update.mediaIds) { int pos = FeedItemUtil.indexOfItemWithMediaId(episodes, mediaId); - if(pos >= 0) { + if (pos >= 0) { listAdapter.notifyItemChanged(pos); } } @@ -489,35 +442,22 @@ 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()) .subscribe(data -> { - recyclerView.setVisibility(View.VISIBLE); progLoading.setVisibility(View.GONE); - episodes = data; - itemsLoaded = true; - if (viewsCreated) { - onFragmentLoaded(); - } + onFragmentLoaded(data); }, error -> Log.e(TAG, Log.getStackTraceString(error))); } @@ -540,7 +480,7 @@ public class AllEpisodesFragment extends Fragment { DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId()); final Handler h = new Handler(getActivity().getMainLooper()); - final Runnable r = () -> { + final Runnable r = () -> { FeedMedia media = item.getMedia(); if (media != null && media.hasAlmostEnded() && UserPreferences.isAutoDelete()) { DBWriter.deleteFeedMediaOfItem(getActivity(), media.getId()); @@ -555,7 +495,6 @@ public class AllEpisodesFragment extends Fragment { h.removeCallbacks(r); }); snackbar.show(); - h.postDelayed(r, (int)Math.ceil(snackbar.getDuration() * 1.05f)); + h.postDelayed(r, (int) Math.ceil(snackbar.getDuration() * 1.05f)); } - } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java index b52fd444f..36a39f578 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java @@ -1,7 +1,7 @@ package de.danoeh.antennapod.fragment; -import android.content.Context; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v4.app.ListFragment; import android.util.Log; import android.view.Menu; @@ -10,6 +10,7 @@ import android.view.MenuItem; import android.view.View; import android.widget.ListView; +import java.util.ArrayList; import java.util.List; import de.danoeh.antennapod.R; @@ -27,6 +28,9 @@ import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; 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 */ @@ -38,24 +42,27 @@ public class CompletedDownloadsFragment extends ListFragment { EventDistributor.DOWNLOADLOG_UPDATE | EventDistributor.UNREAD_ITEMS_UPDATE; - private List<FeedItem> items; + private List<FeedItem> items = new ArrayList<>(); private DownloadedEpisodesListAdapter listAdapter; - - private boolean viewCreated = false; - private Disposable disposable; @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); setHasOptionsMenu(true); - loadItems(); + addVerticalPadding(); + addEmptyView(); + + listAdapter = new DownloadedEpisodesListAdapter(getActivity(), itemAccess); + setListAdapter(listAdapter); + setListShown(false); } @Override public void onStart() { super.onStart(); EventDistributor.getInstance().register(contentUpdate); + loadItems(); } @Override @@ -68,104 +75,53 @@ public class CompletedDownloadsFragment extends ListFragment { } @Override - public void onDetach() { - super.onDetach(); - if (disposable != null) { - disposable.dispose(); - } + public void onListItemClick(ListView l, View v, int position, long id) { + super.onListItemClick(l, v, position, id); + position -= l.getHeaderViewsCount(); + long[] ids = FeedItemUtil.getIds(items); + ((MainActivity) requireActivity()).loadChildFragment(ItemFragment.newInstance(ids, position)); } @Override - public void onDestroyView() { - super.onDestroyView(); - listAdapter = null; - viewCreated = false; - if (disposable != null) { - disposable.dispose(); - } + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + inflater.inflate(R.menu.downloads_completed, menu); + menu.findItem(R.id.episode_actions).setVisible(items.size() > 0); } @Override - public void onAttach(Context context) { - super.onAttach(context); - if (viewCreated && items != null) { - onFragmentLoaded(); + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == R.id.episode_actions) { + ((MainActivity) requireActivity()) + .loadChildFragment(EpisodesApplyActionFragment.newInstance(items, ACTION_DELETE | ACTION_ADD_TO_QUEUE)); + return true; } + return false; } - @Override - 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(); - } - + private void addEmptyView() { EmptyViewHandler emptyView = new EmptyViewHandler(getActivity()); emptyView.setTitle(R.string.no_comp_downloads_head_label); emptyView.setMessage(R.string.no_comp_downloads_label); emptyView.attachToListView(getListView()); } - @Override - public void onListItemClick(ListView l, View v, int position, long id) { - super.onListItemClick(l, v, position, id); - position -= l.getHeaderViewsCount(); - long[] ids = FeedItemUtil.getIds(items); - ((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 void addVerticalPadding() { + final ListView lv = getListView(); + lv.setClipToPadding(false); + final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding); + lv.setPadding(0, vertPadding, 0, vertPadding); } private final DownloadedEpisodesListAdapter.ItemAccess itemAccess = new DownloadedEpisodesListAdapter.ItemAccess() { @Override public int getCount() { - return (items != null) ? items.size() : 0; + return items.size(); } @Override public FeedItem getItem(int position) { - if (items != null && 0 <= position && position < items.size()) { + if (0 <= position && position < items.size()) { return items.get(position); } else { return null; @@ -174,7 +130,7 @@ public class CompletedDownloadsFragment extends ListFragment { @Override 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) { disposable.dispose(); } - if (items == null && viewCreated) { - setListShown(false); - } disposable = Observable.fromCallable(DBReader::getDownloadedItems) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { items = result; - if (viewCreated && getActivity() != null) { - onFragmentLoaded(); - } - }, error -> Log.e(TAG, Log.getStackTraceString(error))); + onItemsLoaded(); + }, error -> Log.e(TAG, Log.getStackTraceString(error))); } + private void onItemsLoaded() { + setListShown(true); + listAdapter.notifyDataSetChanged(); + requireActivity().invalidateOptionsMenu(); + } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java index 973772049..4f7ec4050 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java @@ -14,6 +14,7 @@ import android.view.View; import android.widget.ListView; import android.widget.TextView; +import java.util.ArrayList; import java.util.List; import de.danoeh.antennapod.R; @@ -37,18 +38,13 @@ public class DownloadLogFragment extends ListFragment { private static final String TAG = "DownloadLogFragment"; - private List<DownloadStatus> downloadLog; + private List<DownloadStatus> downloadLog = new ArrayList<>(); private DownloadLogAdapter adapter; - - private boolean viewsCreated = false; - private boolean itemsLoaded = false; - private Disposable disposable; @Override public void onStart() { super.onStart(); - setHasOptionsMenu(true); EventDistributor.getInstance().register(contentUpdate); loadItems(); } @@ -57,7 +53,7 @@ public class DownloadLogFragment extends ListFragment { public void onStop() { super.onStop(); EventDistributor.getInstance().unregister(contentUpdate); - if(disposable != null) { + if (disposable != null) { disposable.dispose(); } } @@ -65,6 +61,7 @@ public class DownloadLogFragment extends ListFragment { @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + setHasOptionsMenu(true); // add padding final ListView lv = getListView(); @@ -72,23 +69,16 @@ public class DownloadLogFragment extends ListFragment { final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding); lv.setPadding(0, vertPadding, 0, vertPadding); - viewsCreated = true; - if (itemsLoaded) { - onFragmentLoaded(); - } - EmptyViewHandler emptyView = new EmptyViewHandler(getActivity()); emptyView.setTitle(R.string.no_log_downloads_head_label); emptyView.setMessage(R.string.no_log_downloads_label); emptyView.attachToListView(getListView()); + adapter = new DownloadLogAdapter(getActivity(), itemAccess); + setListAdapter(adapter); } private void onFragmentLoaded() { - if (adapter == null) { - adapter = new DownloadLogAdapter(getActivity(), itemAccess); - setListAdapter(adapter); - } setListShown(true); adapter.notifyDataSetChanged(); getActivity().supportInvalidateOptionsMenu(); @@ -129,12 +119,12 @@ public class DownloadLogFragment extends ListFragment { @Override public int getCount() { - return (downloadLog != null) ? downloadLog.size() : 0; + return downloadLog.size(); } @Override public DownloadStatus getItem(int position) { - if (downloadLog != null && 0 <= position && position < downloadLog.size()) { + if (0 <= position && position < downloadLog.size()) { return downloadLog.get(position); } else { return null; @@ -154,27 +144,23 @@ public class DownloadLogFragment extends ListFragment { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - if(!isAdded()) { + if (!isAdded()) { return; } 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); - MenuItemCompat.setShowAsAction(clearHistory, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); - TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.content_discard}); - clearHistory.setIcon(drawables.getDrawable(0)); - drawables.recycle(); - } + 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); + TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.content_discard}); + clearHistory.setIcon(drawables.getDrawable(0)); + drawables.recycle(); } @Override public void onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); - if (itemsLoaded) { - MenuItem menuItem = menu.findItem(R.id.clear_history_item); - if(menuItem != null) { - menuItem.setVisible(downloadLog != null && !downloadLog.isEmpty()); - } + MenuItem menuItem = menu.findItem(R.id.clear_history_item); + if (menuItem != null) { + menuItem.setVisible(!downloadLog.isEmpty()); } } @@ -194,7 +180,7 @@ public class DownloadLogFragment extends ListFragment { } private void loadItems() { - if(disposable != null) { + if (disposable != null) { disposable.dispose(); } disposable = Observable.fromCallable(DBReader::getDownloadLog) @@ -203,12 +189,8 @@ public class DownloadLogFragment extends ListFragment { .subscribe(result -> { if (result != null) { downloadLog = result; - itemsLoaded = true; - if (viewsCreated) { - onFragmentLoaded(); - } + onFragmentLoaded(); } }, error -> Log.e(TAG, Log.getStackTraceString(error))); } - } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java index d362d5c0b..c273a7033 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java @@ -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; @@ -8,7 +9,8 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; + +import org.greenrobot.eventbus.Subscribe; 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.storage.DBReader; 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 * supports swiping to remove from favorites. */ - public class FavoriteEpisodesFragment extends AllEpisodesFragment { private static final String TAG = "FavoriteEpisodesFrag"; - private static final String PREF_NAME = "PrefFavoriteEpisodesFragment"; @Override - protected boolean showOnlyNewEpisodes() { return true; } + protected boolean showOnlyNewEpisodes() { + return true; + } @Override - protected String getPrefName() { return PREF_NAME; } + protected String getPrefName() { + return PREF_NAME; + } @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); @@ -65,8 +61,8 @@ 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() + ")"); + AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder) viewHolder; + Log.d(TAG, String.format("remove(%s)", holder.getItemId())); if (disposable != null) { disposable.dispose(); @@ -75,8 +71,7 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment { if (item != null) { DBWriter.removeFavoriteItem(item); - Snackbar snackbar = Snackbar.make(root, getString(R.string.removed_item), - Snackbar.LENGTH_LONG); + Snackbar snackbar = Snackbar.make(root, getString(R.string.removed_item), Snackbar.LENGTH_LONG); snackbar.setAction(getString(R.string.undo), v -> DBWriter.addFavoriteItem(item)); snackbar.show(); } @@ -88,6 +83,7 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment { return root; } + @NonNull @Override protected List<FeedItem> loadData() { return DBReader.getFavoriteItemsList(); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java index a2472b071..149718569 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java @@ -36,6 +36,9 @@ import com.joanzapata.iconify.Iconify; import com.joanzapata.iconify.widget.IconButton; 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; @@ -71,9 +74,6 @@ import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; 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. @@ -266,7 +266,6 @@ public class ItemFragment extends Fragment implements OnSwipeGesture { @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - load(); } @Override @@ -274,6 +273,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture { super.onStart(); EventDistributor.getInstance().register(contentUpdate); EventBus.getDefault().register(this); + load(); } @Override @@ -306,19 +306,20 @@ public class ItemFragment extends Fragment implements OnSwipeGesture { @Override public boolean onSwipeLeftToRight() { - Log.d(TAG, "onSwipeLeftToRight()"); - feedItemPos = feedItemPos - 1; - if(feedItemPos < 0) { - feedItemPos = feedItems.length - 1; - } - load(); - return true; + return swipeFeedItem(-1); } @Override public boolean onSwipeRightToLeft() { - Log.d(TAG, "onSwipeRightToLeft()"); - feedItemPos = (feedItemPos + 1) % feedItems.length; + return swipeFeedItem(+1); + } + + 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(); return true; } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java index 6a04758b9..0c75af986 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java @@ -30,6 +30,9 @@ import com.joanzapata.iconify.Iconify; import com.joanzapata.iconify.widget.IconTextView; 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; @@ -71,9 +74,6 @@ import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; 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. @@ -96,8 +96,6 @@ public class ItemlistFragment extends ListFragment { private long feedID; private Feed feed; - private boolean itemsLoaded = false; - private boolean viewsCreated = false; private boolean headerCreated = false; private List<Downloader> downloaderList; @@ -105,7 +103,7 @@ public class ItemlistFragment extends ListFragment { private MoreContentListFooterUtil listFooter; private boolean isUpdatingFeed; - + private TextView txtvTitle; private IconTextView txtvFailure; private ImageView imgvBackground; @@ -146,9 +144,7 @@ public class ItemlistFragment extends ListFragment { super.onStart(); EventDistributor.getInstance().register(contentUpdate); EventBus.getDefault().register(this); - if (viewsCreated && itemsLoaded) { - onFragmentLoaded(); - } + loadItems(); } @Override @@ -156,7 +152,6 @@ public class ItemlistFragment extends ListFragment { super.onResume(); ((MainActivity)getActivity()).getSupportActionBar().setTitle(""); updateProgressBarVisibility(); - loadItems(); } @Override @@ -177,7 +172,6 @@ public class ItemlistFragment extends ListFragment { private void resetViewState() { adapter = null; - viewsCreated = false; listFooter = null; } @@ -190,45 +184,43 @@ public class ItemlistFragment extends ListFragment { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - if(!isAdded()) { + if (!isAdded()) { return; } super.onCreateOptionsMenu(menu, inflater); - if (itemsLoaded) { - FeedMenuHandler.onCreateOptionsMenu(inflater, 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(); - if (itemsLoaded) { - ((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance(s, feed.getId())); - } - return true; - } + FeedMenuHandler.onCreateOptionsMenu(inflater, menu); - @Override - public boolean onQueryTextChange(String s) { - return false; + 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(); + if (feed != null) { + ((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance(s, feed.getId())); } - }); - if(feed == null || feed.getLink() == null) { - menu.findItem(R.id.share_link_item).setVisible(false); - menu.findItem(R.id.visit_website_item).setVisible(false); + return true; } - 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 public void onPrepareOptionsMenu(Menu menu) { - if (itemsLoaded) { + if (feed != null) { FeedMenuHandler.onPrepareOptionsMenu(menu, feed); } } @@ -341,11 +333,6 @@ public class ItemlistFragment extends ListFragment { super.onViewCreated(view, savedInstanceState); registerForContextMenu(getListView()); - - viewsCreated = true; - if (itemsLoaded) { - onFragmentLoaded(); - } } @Override @@ -503,7 +490,7 @@ public class ItemlistFragment extends ListFragment { butShowInfo.setOnClickListener(v -> showFeedInfo()); imgvCover.setOnClickListener(v -> showFeedInfo()); butShowSettings.setOnClickListener(v -> { - if (viewsCreated && itemsLoaded) { + if (feed != null) { Intent startIntent = new Intent(getActivity(), FeedSettingsActivity.class); startIntent.putExtra(FeedSettingsActivity.EXTRA_FEED_ID, feed.getId()); @@ -514,7 +501,7 @@ public class ItemlistFragment extends ListFragment { } private void showFeedInfo() { - if (viewsCreated && itemsLoaded) { + if (feed != null) { Intent startIntent = new Intent(getActivity(), FeedInfoActivity.class); startIntent.putExtra(FeedInfoActivity.EXTRA_FEED_ID, feed.getId()); @@ -624,10 +611,7 @@ public class ItemlistFragment extends ListFragment { .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { feed = result.orElse(null); - itemsLoaded = true; - if (viewsCreated) { - onFragmentLoaded(); - } + onFragmentLoaded(); }, error -> Log.e(TAG, Log.getStackTraceString(error))); } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java index 5751855c7..6da68d369 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java @@ -1,40 +1,37 @@ 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.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.TextView; + import java.util.List; + import de.danoeh.antennapod.R; 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.storage.DBReader; -import de.danoeh.antennapod.core.util.FeedItemUtil; - /** * Like 'EpisodesFragment' except that it only shows new episodes and * supports swiping to mark as read. */ - public class NewEpisodesFragment extends AllEpisodesFragment { public static final String TAG = "NewEpisodesFragment"; private static final String PREF_NAME = "PrefNewEpisodesFragment"; - @Override - protected boolean showOnlyNewEpisodes() { return true; } @Override - protected String getPrefName() { return PREF_NAME; } + protected boolean showOnlyNewEpisodes() { + return true; + } @Override - protected void resetViewState() { - super.resetViewState(); + protected String getPrefName() { + return PREF_NAME; } @Override @@ -42,10 +39,10 @@ public class NewEpisodesFragment extends AllEpisodesFragment { 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); @@ -57,7 +54,7 @@ public class NewEpisodesFragment extends AllEpisodesFragment { @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) { - AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder)viewHolder; + AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder) viewHolder; markItemAsSeenWithUndo(holder.getFeedItem()); } @@ -75,6 +72,7 @@ public class NewEpisodesFragment extends AllEpisodesFragment { super.onSelectedChanged(viewHolder, actionState); } + @Override public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { @@ -94,9 +92,9 @@ public class NewEpisodesFragment extends AllEpisodesFragment { return root; } + @NonNull @Override protected List<FeedItem> loadData() { return DBReader.getNewItemsList(); } - } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java index da11383a5..b63936643 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java @@ -1,6 +1,5 @@ package de.danoeh.antennapod.fragment; -import android.content.Context; import android.content.res.TypedArray; import android.os.Bundle; import android.support.annotation.NonNull; @@ -13,6 +12,10 @@ import android.view.MenuItem; import android.view.View; import android.widget.ListView; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + import java.util.List; import de.danoeh.antennapod.R; @@ -34,9 +37,6 @@ import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; 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 { @@ -47,23 +47,10 @@ public class PlaybackHistoryFragment extends ListFragment { private List<FeedItem> playbackHistory; private FeedItemlistAdapter adapter; - - private boolean itemsLoaded = false; - private boolean viewsCreated = false; - private List<Downloader> downloaderList; - private Disposable disposable; @Override - public void onAttach(Context context) { - super.onAttach(context); - if (viewsCreated && itemsLoaded) { - onFragmentLoaded(); - } - } - - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); @@ -80,16 +67,16 @@ public class PlaybackHistoryFragment extends ListFragment { final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding); lv.setPadding(0, vertPadding, 0, vertPadding); - viewsCreated = true; - if (itemsLoaded) { - onFragmentLoaded(); - } - EmptyViewHandler emptyView = new EmptyViewHandler(getActivity()); emptyView.setTitle(R.string.no_history_head_label); emptyView.setMessage(R.string.no_history_label); 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 @@ -105,34 +92,17 @@ public class PlaybackHistoryFragment extends ListFragment { super.onStop(); EventBus.getDefault().unregister(this); EventDistributor.getInstance().unregister(contentUpdate); - if(disposable != null) { - disposable.dispose(); - } - } - - @Override - public void onDetach() { - super.onDetach(); - if(disposable != null) { + if (disposable != null) { disposable.dispose(); } } - @Override - public void onDestroyView() { - super.onDestroyView(); - adapter = null; - viewsCreated = false; - } - @Subscribe(sticky = true) public void onEvent(DownloadEvent event) { Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]"); DownloaderUpdate update = event.update; downloaderList = update.downloaders; - if (adapter != null) { - adapter.notifyDataSetChanged(); - } + adapter.notifyDataSetChanged(); } @Override @@ -145,27 +115,23 @@ public class PlaybackHistoryFragment extends ListFragment { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - if(!isAdded()) { + if (!isAdded()) { return; } 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); - MenuItemCompat.setShowAsAction(clearHistory, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); - TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.content_discard}); - clearHistory.setIcon(drawables.getDrawable(0)); - drawables.recycle(); - } + 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); + TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.content_discard}); + clearHistory.setIcon(drawables.getDrawable(0)); + drawables.recycle(); } @Override public void onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); - if (itemsLoaded) { - MenuItem menuItem = menu.findItem(R.id.clear_history_item); - if (menuItem != null) { - menuItem.setVisible(playbackHistory != null && !playbackHistory.isEmpty()); - } + MenuItem menuItem = menu.findItem(R.id.clear_history_item); + if (menuItem != null) { + menuItem.setVisible(playbackHistory != null && !playbackHistory.isEmpty()); } } @@ -211,14 +177,6 @@ public class PlaybackHistoryFragment extends ListFragment { }; 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(); getActivity().supportInvalidateOptionsMenu(); } @@ -277,10 +235,7 @@ public class PlaybackHistoryFragment extends ListFragment { .subscribe(result -> { if (result != null) { playbackHistory = result; - itemsLoaded = true; - if (viewsCreated) { - onFragmentLoaded(); - } + onFragmentLoaded(); } }, error -> Log.e(TAG, Log.getStackTraceString(error))); } @@ -291,5 +246,4 @@ public class PlaybackHistoryFragment extends ListFragment { DBReader.loadAdditionalFeedItemListData(history); return history; } - } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java index 718502ea2..31b9d7b8d 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java @@ -7,6 +7,10 @@ import android.view.View; import android.widget.ListView; import android.widget.Toast; +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; + +import java.util.ArrayList; import java.util.List; 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.DownloadRequester; 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 @@ -32,7 +34,7 @@ public class RunningDownloadsFragment extends ListFragment { private static final String TAG = "RunningDownloadsFrag"; private DownloadlistAdapter adapter; - private List<Downloader> downloaderList; + private List<Downloader> downloaderList = new ArrayList<>(); @Override public void onViewCreated(View view, Bundle savedInstanceState) { @@ -70,7 +72,6 @@ public class RunningDownloadsFragment extends ListFragment { public void onDestroy() { super.onDestroy(); setListAdapter(null); - adapter = null; } @Subscribe(sticky = true) @@ -78,21 +79,18 @@ public class RunningDownloadsFragment extends ListFragment { Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]"); DownloaderUpdate update = event.update; downloaderList = update.downloaders; - if (adapter != null) { - adapter.notifyDataSetChanged(); - } + adapter.notifyDataSetChanged(); } - private final DownloadlistAdapter.ItemAccess itemAccess = new DownloadlistAdapter.ItemAccess() { @Override public int getCount() { - return (downloaderList != null) ? downloaderList.size() : 0; + return downloaderList.size(); } @Override public Downloader getItem(int position) { - if (downloaderList != null && 0 <= position && position < downloaderList.size()) { + if (0 <= position && position < downloaderList.size()) { return downloaderList.get(position); } else { return null; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java index 1d7ac8824..0892bce0a 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java @@ -14,6 +14,7 @@ import android.view.MenuItem; import android.view.View; import android.widget.ListView; +import java.util.ArrayList; import java.util.List; import de.danoeh.antennapod.R; @@ -40,11 +41,7 @@ public class SearchFragment extends ListFragment { private static final String ARG_FEED = "feed"; private SearchlistAdapter searchAdapter; - private List<SearchResult> searchResults; - - private boolean viewCreated = false; - private boolean itemsLoaded = false; - + private List<SearchResult> searchResults = new ArrayList<>(); private Disposable disposable; /** @@ -74,13 +71,13 @@ public class SearchFragment extends ListFragment { super.onCreate(savedInstanceState); setRetainInstance(true); setHasOptionsMenu(true); - search(); } @Override public void onStart() { super.onStart(); EventDistributor.getInstance().register(contentUpdate); + search(); } @Override @@ -93,21 +90,6 @@ public class SearchFragment extends ListFragment { } @Override - public void onDetach() { - super.onDetach(); - if(disposable != null) { - disposable.dispose(); - } - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - searchAdapter = null; - viewCreated = false; - } - - @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); @@ -118,10 +100,9 @@ public class SearchFragment extends ListFragment { lv.setPadding(0, vertPadding, 0, vertPadding); ((AppCompatActivity) getActivity()).getSupportActionBar().setTitle(R.string.search_label); - viewCreated = true; - if (itemsLoaded) { - onFragmentLoaded(); - } + + searchAdapter = new SearchlistAdapter(getActivity(), itemAccess); + setListAdapter(searchAdapter); } @Override @@ -142,28 +123,26 @@ public class SearchFragment extends ListFragment { @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); - if (itemsLoaded) { - 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); - final SearchView sv = new SearchView(getActivity()); - sv.setQueryHint(getString(R.string.search_hint)); - sv.setQuery(getArguments().getString(ARG_QUERY), false); - sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { - @Override - public boolean onQueryTextSubmit(String s) { - getArguments().putString(ARG_QUERY, s); - itemsLoaded = false; - search(); - return true; - } - - @Override - public boolean onQueryTextChange(String s) { - return false; - } - }); - MenuItemCompat.setActionView(item, sv); - } + 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); + final SearchView sv = new SearchView(getActivity()); + sv.setQueryHint(getString(R.string.search_hint)); + sv.setQuery(getArguments().getString(ARG_QUERY), false); + sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String s) { + sv.clearFocus(); + getArguments().putString(ARG_QUERY, s); + search(); + return true; + } + + @Override + public boolean onQueryTextChange(String s) { + return false; + } + }); + MenuItemCompat.setActionView(item, sv); } private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() { @@ -176,14 +155,9 @@ public class SearchFragment extends ListFragment { } }; - private void onFragmentLoaded() { - if (searchAdapter == null) { - searchAdapter = new SearchlistAdapter(getActivity(), itemAccess); - setListAdapter(searchAdapter); - } + private void onSearchResults(List<SearchResult> results) { + searchResults = results; searchAdapter.notifyDataSetChanged(); - setListShown(true); - String query = getArguments().getString(ARG_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() { @Override public int getCount() { - return (searchResults != null) ? searchResults.size() : 0; + return searchResults.size(); } @Override public SearchResult getItem(int position) { - if (searchResults != null && 0 <= position && position < searchResults.size()) { + if (0 <= position && position < searchResults.size()) { return searchResults.get(position); } else { return null; @@ -204,24 +178,14 @@ public class SearchFragment extends ListFragment { } }; - private void search() { if(disposable != null) { disposable.dispose(); } - if (viewCreated && !itemsLoaded) { - setListShown(false); - } disposable = Observable.fromCallable(this::performSearch) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(result -> { - itemsLoaded = true; - searchResults = result; - if (viewCreated) { - onFragmentLoaded(); - } - }, error -> Log.e(TAG, Log.getStackTraceString(error))); + .subscribe(this::onSearchResults, error -> Log.e(TAG, Log.getStackTraceString(error))); } @NonNull @@ -232,5 +196,4 @@ public class SearchFragment extends ListFragment { Context context = getActivity(); return FeedSearcher.performSearch(context, query, feed); } - } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java index 75da522d1..25fe0e6e3 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java @@ -1,9 +1,11 @@ package de.danoeh.antennapod.fragment; +import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.os.Bundle; +import android.support.annotation.StringRes; import android.support.v4.app.Fragment; import android.util.Log; import android.view.ContextMenu; @@ -16,6 +18,8 @@ import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.GridView; +import java.util.concurrent.Callable; + import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.SubscriptionsAdapter; @@ -56,16 +60,13 @@ public class SubscriptionFragment extends Fragment { private Disposable disposable; private SharedPreferences prefs; - public SubscriptionFragment() { - } - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); setHasOptionsMenu(true); - prefs = getActivity().getSharedPreferences(PREFS, Context.MODE_PRIVATE); + prefs = requireActivity().getSharedPreferences(PREFS, Context.MODE_PRIVATE); } @Override @@ -123,23 +124,25 @@ public class SubscriptionFragment extends Fragment { public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); subscriptionAdapter = new SubscriptionsAdapter((MainActivity)getActivity(), itemAccess); - subscriptionGridLayout.setAdapter(subscriptionAdapter); - - loadSubscriptions(); - subscriptionGridLayout.setOnItemClickListener(subscriptionAdapter); if (getActivity() instanceof MainActivity) { ((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.subscriptions_label); } + } + @Override + public void onStart() { + super.onStart(); EventDistributor.getInstance().register(contentUpdate); + loadSubscriptions(); } @Override - public void onDestroy() { - super.onDestroy(); + public void onStop() { + super.onStop(); + EventDistributor.getInstance().unregister(contentUpdate); if(disposable != null) { disposable.dispose(); } @@ -172,7 +175,7 @@ public class SubscriptionFragment extends Fragment { Feed feed = (Feed)selectedObject; - MenuInflater inflater = getActivity().getMenuInflater(); + MenuInflater inflater = requireActivity().getMenuInflater(); inflater.inflate(R.menu.nav_feed_context, menu); menu.setHeaderTitle(feed.getTitle()); @@ -182,7 +185,6 @@ public class SubscriptionFragment extends Fragment { @Override public boolean onContextItemSelected(MenuItem item) { - final int position = mPosition; mPosition = -1; // reset if(position < 0) { @@ -198,83 +200,72 @@ public class SubscriptionFragment extends Fragment { Feed feed = (Feed)selectedObject; switch(item.getItemId()) { case R.id.mark_all_seen_item: - ConfirmationDialog markAllSeenConfirmationDialog = new ConfirmationDialog(getActivity(), + displayConfirmationDialog( R.string.mark_all_seen_label, - R.string.mark_all_seen_confirmation_msg) { - - @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(); + R.string.mark_all_seen_confirmation_msg, + () -> DBWriter.markFeedSeen(feed.getId())); return true; case R.id.mark_all_read_item: - ConfirmationDialog markAllReadConfirmationDialog = new ConfirmationDialog(getActivity(), + displayConfirmationDialog( R.string.mark_all_read_label, - R.string.mark_all_read_confirmation_msg) { - - @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(); + R.string.mark_all_read_confirmation_msg, + () -> DBWriter.markFeedRead(feed.getId())); return true; case R.id.rename_item: new RenameFeedDialog(getActivity(), feed).show(); return true; case R.id.remove_item: - final FeedRemover remover = new FeedRemover(getContext(), 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(); + displayRemoveFeedDialog(feed); return true; default: return super.onContextItemSelected(item); } } - @Override - public void onResume() { - super.onResume(); - loadSubscriptions(); + private void displayRemoveFeedDialog(Feed feed) { + final FeedRemover remover = new FeedRemover(getContext(), feed) { + @Override + 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() { diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/DownloaderUpdate.java b/core/src/main/java/de/danoeh/antennapod/core/event/DownloaderUpdate.java index dcb033267..7ca6f78de 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/event/DownloaderUpdate.java +++ b/core/src/main/java/de/danoeh/antennapod/core/event/DownloaderUpdate.java @@ -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) { |