Merge pull request #1292 from mfietz/issue/1290-NPE

NPE: ItemFragment Loader.loadInBackground
This commit is contained in:
Tom Hennen 2015-10-29 17:28:38 -04:00
commit ebd6686ca6
2 changed files with 150 additions and 149 deletions

View File

@ -11,8 +11,6 @@ import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v4.util.Pair; import android.support.v4.util.Pair;
import android.support.v7.widget.PopupMenu; import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
@ -42,12 +40,11 @@ import java.util.List;
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.DefaultActionButtonCallback; import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
import de.danoeh.antennapod.core.asynctask.DBTaskLoader;
import de.danoeh.antennapod.core.asynctask.DownloadObserver; import de.danoeh.antennapod.core.asynctask.DownloadObserver;
import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.feed.EventDistributor;
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.event.QueueEvent;
import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.Downloader; import de.danoeh.antennapod.core.service.download.Downloader;
@ -63,11 +60,15 @@ import de.danoeh.antennapod.core.util.ShareUtils;
import de.danoeh.antennapod.core.util.playback.Timeline; import de.danoeh.antennapod.core.util.playback.Timeline;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
import de.greenrobot.event.EventBus; import de.greenrobot.event.EventBus;
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
/** /**
* Displays information about a FeedItem and actions. * Displays information about a FeedItem and actions.
*/ */
public class ItemFragment extends Fragment implements LoaderManager.LoaderCallbacks<Pair<FeedItem, LongList>> { public class ItemFragment extends Fragment {
private static final String TAG = "ItemFragment"; private static final String TAG = "ItemFragment";
@ -113,6 +114,8 @@ public class ItemFragment extends Fragment implements LoaderManager.LoaderCallba
private ImageButton butMore; private ImageButton butMore;
private PopupMenu popupMenu; private PopupMenu popupMenu;
private Subscription subscription;
/** /**
* URL that was selected via long-press. * URL that was selected via long-press.
*/ */
@ -127,55 +130,6 @@ public class ItemFragment extends Fragment implements LoaderManager.LoaderCallba
itemID = getArguments().getLong(ARG_FEEDITEM, -1); itemID = getArguments().getLong(ARG_FEEDITEM, -1);
} }
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getLoaderManager().initLoader(0, null, this);
Toolbar toolbar = ((MainActivity) getActivity()).getToolbar();
toolbar.addView(header);
}
@Override
public void onStart() {
super.onStart();
EventDistributor.getInstance().register(contentUpdate);
EventBus.getDefault().register(this);
if (downloadObserver != null) {
downloadObserver.setActivity(getActivity());
downloadObserver.onResume();
}
if (itemsLoaded) {
onFragmentLoaded();
}
}
@Override
public void onStop() {
super.onStop();
EventDistributor.getInstance().unregister(contentUpdate);
EventBus.getDefault().unregister(this);
}
private void resetViewState() {
if (downloadObserver != null) {
downloadObserver.onPause();
}
Toolbar toolbar = ((MainActivity) getActivity()).getToolbar();
toolbar.removeView(header);
}
@Override
public void onDestroyView() {
super.onDestroyView();
resetViewState();
if (webvDescription != null && root != null) {
root.removeView(webvDescription);
webvDescription.destroy();
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB) @TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override @Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
@ -195,19 +149,18 @@ public class ItemFragment extends Fragment implements LoaderManager.LoaderCallba
webvDescription = (WebView) layout.findViewById(R.id.webvDescription); webvDescription = (WebView) layout.findViewById(R.id.webvDescription);
if (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) { if (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
if (Build.VERSION.SDK_INT >= 11 if (Build.VERSION.SDK_INT >= 11
&& Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { && Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
webvDescription.setLayerType(View.LAYER_TYPE_SOFTWARE, null); webvDescription.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
} }
webvDescription.setBackgroundColor(getResources().getColor( webvDescription.setBackgroundColor(getResources().getColor(
R.color.black)); R.color.black));
} }
webvDescription.getSettings().setUseWideViewPort(false); webvDescription.getSettings().setUseWideViewPort(false);
webvDescription.getSettings().setLayoutAlgorithm( webvDescription.getSettings().setLayoutAlgorithm(
WebSettings.LayoutAlgorithm.NARROW_COLUMNS); WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
webvDescription.getSettings().setLoadWithOverviewMode(true); webvDescription.getSettings().setLoadWithOverviewMode(true);
webvDescription.setOnLongClickListener(webViewLongClickListener); webvDescription.setOnLongClickListener(webViewLongClickListener);
webvDescription.setWebViewClient(new WebViewClient() { webvDescription.setWebViewClient(new WebViewClient() {
@Override @Override
public boolean shouldOverrideUrlLoading(WebView view, String url) { public boolean shouldOverrideUrlLoading(WebView view, String url) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
@ -243,74 +196,111 @@ public class ItemFragment extends Fragment implements LoaderManager.LoaderCallba
((MainActivity) getActivity()).dismissChildFragment(); ((MainActivity) getActivity()).dismissChildFragment();
} }
} }
} }
); );
butAction2.setOnClickListener(new View.OnClickListener() butAction2.setOnClickListener(v -> {
if (item == null) {
return;
}
{ if (item.hasMedia()) {
@Override FeedMedia media = item.getMedia();
public void onClick(View v) { if (!media.isDownloaded()) {
if (item == null) { DBTasks.playMedia(getActivity(), media, true, true, true);
return; ((MainActivity) getActivity()).dismissChildFragment();
} } else {
DBWriter.deleteFeedMediaOfItem(getActivity(), media.getId());
if (item.hasMedia()) { }
FeedMedia media = item.getMedia(); } else if (item.getLink() != null) {
if (!media.isDownloaded()) { Uri uri = Uri.parse(item.getLink());
DBTasks.playMedia(getActivity(), media, true, true, true); getActivity().startActivity(new Intent(Intent.ACTION_VIEW, uri));
((MainActivity) getActivity()).dismissChildFragment(); }
} else { }
DBWriter.deleteFeedMediaOfItem(getActivity(), media.getId());
}
} else if (item.getLink() != null) {
Uri uri = Uri.parse(item.getLink());
getActivity().startActivity(new Intent(Intent.ACTION_VIEW, uri));
}
}
}
); );
butMore.setOnClickListener(new View.OnClickListener() { butMore.setOnClickListener(v -> {
@Override if (item == null) {
public void onClick(View v) { return;
if (item == null) { }
return; popupMenu.getMenu().clear();
} popupMenu.inflate(R.menu.feeditem_options);
popupMenu.getMenu().clear(); if (item.hasMedia()) {
popupMenu.inflate(R.menu.feeditem_options); FeedItemMenuHandler.onPrepareMenu(getActivity(), popupMenuInterface, item, true, queue);
if (item.hasMedia()) { } else {
FeedItemMenuHandler.onPrepareMenu(getActivity(), popupMenuInterface, item, true, queue); // these are already available via button1 and button2
} else { FeedItemMenuHandler.onPrepareMenu(getActivity(), popupMenuInterface, item, true, queue,
// these are already available via button1 and button2 R.id.mark_read_item, R.id.visit_website_item);
FeedItemMenuHandler.onPrepareMenu(getActivity(), popupMenuInterface, item, true, queue, }
R.id.mark_read_item, R.id.visit_website_item); popupMenu.show();
} }
popupMenu.show();
}
}
); );
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { popupMenu.setOnMenuItemClickListener(menuItem -> {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
try { try {
return FeedItemMenuHandler.onMenuItemClicked(getActivity(), menuItem.getItemId(), item); return FeedItemMenuHandler.onMenuItemClicked(getActivity(), menuItem.getItemId(), item);
} catch (DownloadRequestException e) { } catch (DownloadRequestException e) {
e.printStackTrace(); e.printStackTrace();
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show(); Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
return true; return true;
} }
} }
}
); );
return layout; return layout;
} }
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Toolbar toolbar = ((MainActivity) getActivity()).getToolbar();
toolbar.addView(header);
load();
}
@Override
public void onResume() {
super.onResume();
EventDistributor.getInstance().register(contentUpdate);
EventBus.getDefault().register(this);
if (downloadObserver != null) {
downloadObserver.setActivity(getActivity());
downloadObserver.onResume();
}
if(itemsLoaded) {
updateAppearance();
}
}
@Override
public void onPause() {
super.onPause();
EventDistributor.getInstance().unregister(contentUpdate);
EventBus.getDefault().unregister(this);
}
@Override
public void onDestroyView() {
super.onDestroyView();
resetViewState();
if(subscription != null) {
subscription.unsubscribe();
}
if (webvDescription != null && root != null) {
root.removeView(webvDescription);
webvDescription.destroy();
}
}
private void resetViewState() {
if (downloadObserver != null) {
downloadObserver.onPause();
}
Toolbar toolbar = ((MainActivity) getActivity()).getToolbar();
toolbar.removeView(header);
}
private final FeedItemMenuHandler.MenuInterface popupMenuInterface = new FeedItemMenuHandler.MenuInterface() { private final FeedItemMenuHandler.MenuInterface popupMenuInterface = new FeedItemMenuHandler.MenuInterface() {
@Override @Override
public void setItemVisibility(int id, boolean visible) { public void setItemVisibility(int id, boolean visible) {
@ -409,11 +399,6 @@ public class ItemFragment extends Fragment implements LoaderManager.LoaderCallba
} }
} }
public void onEvent(QueueEvent event) {
Log.d(TAG, "onEvent(" + event + ")");
getLoaderManager().restartLoader(0, null, ItemFragment.this);
}
private View.OnLongClickListener webViewLongClickListener = new View.OnLongClickListener() { private View.OnLongClickListener webViewLongClickListener = new View.OnLongClickListener() {
@Override @Override
@ -491,46 +476,18 @@ public class ItemFragment extends Fragment implements LoaderManager.LoaderCallba
} }
} }
@Override public void onEventMainThread(QueueEvent event) {
public Loader<Pair<FeedItem,LongList>> onCreateLoader(int id, Bundle args) { if(event.contains(itemID)) {
return new DBTaskLoader<Pair<FeedItem,LongList>>(getActivity()) { updateAppearance();
@Override
public Pair<FeedItem,LongList> loadInBackground() {
FeedItem data1 = DBReader.getFeedItem(itemID);
if (data1 != null) {
Timeline t = new Timeline(getActivity(), data1);
webviewData = t.processShownotes(false);
}
LongList data2 = DBReader.getQueueIDList();
return Pair.create(data1, data2);
}
};
}
@Override
public void onLoadFinished(Loader<Pair<FeedItem,LongList>> loader, Pair<FeedItem,LongList> data) {
if (data != null) {
item = data.first;
queue = data.second;
if (!itemsLoaded) {
itemsLoaded = true;
onFragmentLoaded();
} else {
updateAppearance();
}
} }
} }
@Override
public void onLoaderReset(Loader<Pair<FeedItem,LongList>> loader) {
}
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() { private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override @Override
public void update(EventDistributor eventDistributor, Integer arg) { public void update(EventDistributor eventDistributor, Integer arg) {
if ((arg & EVENTS) != 0) { if ((arg & EVENTS) != 0) {
getLoaderManager().restartLoader(0, null, ItemFragment.this); updateAppearance();
} }
} }
}; };
@ -545,4 +502,36 @@ public class ItemFragment extends Fragment implements LoaderManager.LoaderCallba
} }
} }
}; };
private void load() {
if(subscription != null) {
subscription.unsubscribe();
}
subscription = Observable.defer(() -> Observable.just(loadInBackground()))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
item = result.first;
queue = result.second;
if (!itemsLoaded) {
itemsLoaded = true;
onFragmentLoaded();
} else {
updateAppearance();
}
}, error -> {
Log.e(TAG, Log.getStackTraceString(error));
});
}
private Pair<FeedItem,LongList> loadInBackground() {
FeedItem data1 = DBReader.getFeedItem(itemID);
if (data1 != null) {
Timeline t = new Timeline(getActivity(), data1);
webviewData = t.processShownotes(false);
}
LongList data2 = DBReader.getQueueIDList();
return Pair.create(data1, data2);
}
} }

View File

@ -41,6 +41,18 @@ public class QueueEvent {
this.position = position; this.position = position;
} }
public boolean contains(long id) {
if(item != null) {
return item.getId() == id;
}
for(FeedItem item : items) {
if(item.getId() == id) {
return true;
}
}
return false;
}
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)