Switch feed story list to correctly use loaders.

This commit is contained in:
dosiecki 2014-10-31 01:00:19 -07:00 committed by Samuel Clay
parent 37b61e2dcc
commit 6f9d2f2bdd
8 changed files with 78 additions and 88 deletions

View file

@ -1,8 +1,5 @@
package com.newsblur.activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.app.DialogFragment;
import android.app.FragmentTransaction;
@ -11,8 +8,6 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import com.newsblur.R;
import com.newsblur.database.DatabaseConstants;
import com.newsblur.database.FeedProvider;
import com.newsblur.domain.Feed;
import com.newsblur.fragment.DeleteFeedFragment;
import com.newsblur.fragment.FeedItemListFragment;
@ -25,33 +20,23 @@ import com.newsblur.util.StoryOrder;
public class FeedItemsList extends ItemsList {
public static final String EXTRA_FEED = "feedId";
public static final String EXTRA_FEED_TITLE = "feedTitle";
public static final String EXTRA_FOLDER_NAME = "folderName";
private String feedId;
private String feedTitle;
public static final String EXTRA_FEED = "feed";
public static final String EXTRA_FOLDER_NAME = "folderName";
private Feed feed;
private String folderName;
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
feedId = getIntent().getStringExtra(EXTRA_FEED);
feedTitle = getIntent().getStringExtra(EXTRA_FEED_TITLE);
feed = (Feed) getIntent().getSerializableExtra(EXTRA_FEED);
folderName = getIntent().getStringExtra(EXTRA_FOLDER_NAME);
final Uri feedUri = FeedProvider.FEEDS_URI.buildUpon().appendPath(feedId).build();
Cursor cursor = getContentResolver().query(feedUri, null, DatabaseConstants.getStorySelectionFromState(currentState), null, null);
if (cursor.getCount() > 0) {
cursor.moveToFirst();
Feed feed = Feed.fromCursor(cursor);
setTitle(feed.title);
}
cursor.close();
super.onCreate(bundle);
setTitle(feed.title);
itemListFragment = (FeedItemListFragment) fragmentManager.findFragmentByTag(FeedItemListFragment.class.getName());
if (itemListFragment == null) {
itemListFragment = FeedItemListFragment.newInstance(feedId, currentState, getDefaultFeedView());
itemListFragment = FeedItemListFragment.newInstance(feed, currentState, getDefaultFeedView());
itemListFragment.setRetainInstance(true);
FragmentTransaction listTransaction = fragmentManager.beginTransaction();
listTransaction.add(R.id.activity_itemlist_container, itemListFragment, FeedItemListFragment.class.getName());
@ -61,11 +46,11 @@ public class FeedItemsList extends ItemsList {
@Override
protected FeedSet createFeedSet() {
return FeedSet.singleFeed(getIntent().getStringExtra(EXTRA_FEED));
return FeedSet.singleFeed(feed.feedId);
}
public void deleteFeed() {
DialogFragment deleteFeedFragment = DeleteFeedFragment.newInstance(Long.parseLong(feedId), feedTitle, folderName);
DialogFragment deleteFeedFragment = DeleteFeedFragment.newInstance(feed, folderName);
deleteFeedFragment.show(fragmentManager, "dialog");
}
@ -93,32 +78,32 @@ public class FeedItemsList extends ItemsList {
@Override
protected StoryOrder getStoryOrder() {
return PrefsUtils.getStoryOrderForFeed(this, feedId);
return PrefsUtils.getStoryOrderForFeed(this, feed.feedId);
}
@Override
public void updateStoryOrderPreference(StoryOrder newValue) {
PrefsUtils.setStoryOrderForFeed(this, feedId, newValue);
PrefsUtils.setStoryOrderForFeed(this, feed.feedId, newValue);
}
@Override
protected void updateReadFilterPreference(ReadFilter newValue) {
PrefsUtils.setReadFilterForFeed(this, feedId, newValue);
PrefsUtils.setReadFilterForFeed(this, feed.feedId, newValue);
}
@Override
protected ReadFilter getReadFilter() {
return PrefsUtils.getReadFilterForFeed(this, feedId);
return PrefsUtils.getReadFilterForFeed(this, feed.feedId);
}
@Override
protected DefaultFeedView getDefaultFeedView() {
return PrefsUtils.getDefaultFeedViewForFeed(this, feedId);
return PrefsUtils.getDefaultFeedViewForFeed(this, feed.feedId);
}
@Override
public void defaultFeedViewChanged(DefaultFeedView value) {
PrefsUtils.setDefaultFeedViewForFeed(this, feedId, value);
PrefsUtils.setDefaultFeedViewForFeed(this, feed.feedId, value);
if (itemListFragment != null) {
itemListFragment.setDefaultFeedView(value);
}

View file

@ -8,6 +8,7 @@ import android.database.Cursor;
import android.graphics.Color;
import android.graphics.Typeface;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

View file

@ -5,10 +5,14 @@ import android.database.Cursor;
import android.text.TextUtils;
import android.util.Log;
import java.io.Serializable;
import com.google.gson.annotations.SerializedName;
import com.newsblur.database.DatabaseConstants;
public class Feed implements Comparable<Feed> {
public class Feed implements Comparable<Feed>, Serializable {
private static final long serialVersionUID = 0L;
@SerializedName("id")
public String feedId;

View file

@ -2,6 +2,8 @@ package com.newsblur.fragment;
import com.newsblur.R;
import com.newsblur.activity.Main;
import com.newsblur.domain.Feed;
import com.newsblur.domain.SocialFeed;
import com.newsblur.network.APIManager;
import com.newsblur.util.FeedUtils;
@ -20,15 +22,25 @@ import android.widget.TextView;
import android.widget.Toast;
public class DeleteFeedFragment extends DialogFragment {
private static final String FEED_ID = "feed_url";
private static final String FEED_ID = "feed_id";
private static final String FEED_NAME = "feed_name";
private static final String FOLDER_NAME = "folder_name";
public static DeleteFeedFragment newInstance(final long feedId, final String feedName, final String folderName) {
public static DeleteFeedFragment newInstance(Feed feed, String folderName) {
DeleteFeedFragment frag = new DeleteFeedFragment();
Bundle args = new Bundle();
args.putLong(FEED_ID, feedId);
args.putString(FEED_NAME, feedName);
args.putString(FEED_ID, feed.feedId);
args.putString(FEED_NAME, feed.title);
args.putString(FOLDER_NAME, folderName);
frag.setArguments(args);
return frag;
}
public static DeleteFeedFragment newInstance(SocialFeed feed, String folderName) {
DeleteFeedFragment frag = new DeleteFeedFragment();
Bundle args = new Bundle();
args.putString(FEED_ID, feed.userId);
args.putString(FEED_NAME, feed.feedTitle);
args.putString(FOLDER_NAME, folderName);
frag.setArguments(args);
return frag;
@ -41,7 +53,7 @@ public class DeleteFeedFragment extends DialogFragment {
builder.setPositiveButton(R.string.alert_dialog_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
FeedUtils.deleteFeed(getArguments().getLong(FEED_ID), getArguments().getString(FOLDER_NAME), getActivity(), new APIManager(getActivity()));
FeedUtils.deleteFeed(getArguments().getString(FEED_ID), getArguments().getString(FOLDER_NAME), getActivity(), new APIManager(getActivity()));
// if called from main view then refresh otherwise it was
// called from the feed view so finish
Activity activity = DeleteFeedFragment.this.getActivity();

View file

@ -32,14 +32,15 @@ import com.newsblur.view.FeedItemViewBinder;
public class FeedItemListFragment extends ItemListFragment implements OnItemClickListener {
private String feedId;
private Feed feed;
private ListView itemList;
public static FeedItemListFragment newInstance(String feedId, StateFilter currentState, DefaultFeedView defaultFeedView) {
public static FeedItemListFragment newInstance(Feed feed, StateFilter currentState, DefaultFeedView defaultFeedView) {
FeedItemListFragment feedItemFragment = new FeedItemListFragment();
Bundle args = new Bundle();
args.putSerializable("currentState", currentState);
args.putString("feedId", feedId);
args.putSerializable("feed", feed);
args.putSerializable("defaultFeedView", defaultFeedView);
feedItemFragment.setArguments(args);
@ -49,61 +50,50 @@ public class FeedItemListFragment extends ItemListFragment implements OnItemClic
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
feedId = getArguments().getString("feedId");
feed = (Feed) getArguments().getSerializable("feed");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_itemlist, null);
ListView itemList = (ListView) v.findViewById(R.id.itemlistfragment_list);
itemList = (ListView) v.findViewById(R.id.itemlistfragment_list);
setupBezelSwipeDetector(itemList);
itemList.setEmptyView(v.findViewById(R.id.empty_view));
ContentResolver contentResolver = getActivity().getContentResolver();
// TODO: defer creation of the adapter until the loader's first callback so we don't leak this first stories cursor
Cursor storiesCursor = dbHelper.getStoriesCursor(getFeedSet(), currentState);
Uri feedUri = FeedProvider.FEEDS_URI.buildUpon().appendPath(feedId).build();
Cursor feedCursor = contentResolver.query(feedUri, null, null, null, null);
if (feedCursor.getCount() < 1) {
// This shouldn't happen, but crash reports indicate that it does (very rarely).
// If we are told to create an item list for a feed, but then can't find that feed ID in the DB,
// something is very wrong, and we won't be able to recover, so just force the user back to the
// feed list until we have a better understanding of how to prevent this.
Log.w(this.getClass().getName(), "Feed not found in DB, can't create item list.");
getActivity().finish();
return v;
itemList.setOnScrollListener(this);
if (adapter != null) {
// normally the list gets set up when the adapter is created, but sometimes
// onCreateView gets re-called.
itemList.setAdapter(adapter);
itemList.setOnItemClickListener(this);
itemList.setOnCreateContextMenuListener(this);
}
feedCursor.moveToFirst();
Feed feed = Feed.fromCursor(feedCursor);
feedCursor.close();
String[] groupFrom = new String[] { DatabaseConstants.STORY_TITLE, DatabaseConstants.STORY_SHORT_CONTENT, DatabaseConstants.STORY_AUTHORS, DatabaseConstants.STORY_TIMESTAMP, DatabaseConstants.STORY_INTELLIGENCE_AUTHORS };
int[] groupTo = new int[] { R.id.row_item_title, R.id.row_item_content, R.id.row_item_author, R.id.row_item_date, R.id.row_item_sidebar };
// create the adapter before starting the loader, since the callback updates the adapter
adapter = new FeedItemsAdapter(getActivity(), feed, R.layout.row_item, storiesCursor, groupFrom, groupTo, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
getLoaderManager().initLoader(ITEMLIST_LOADER , null, this);
itemList.setOnScrollListener(this);
adapter.setViewBinder(new FeedItemViewBinder(getActivity()));
itemList.setAdapter(adapter);
itemList.setOnItemClickListener(this);
itemList.setOnCreateContextMenuListener(this);
return v;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
if ((adapter == null) && (cursor != null)) {
String[] groupFrom = new String[] { DatabaseConstants.STORY_TITLE, DatabaseConstants.STORY_SHORT_CONTENT, DatabaseConstants.STORY_AUTHORS, DatabaseConstants.STORY_TIMESTAMP, DatabaseConstants.STORY_INTELLIGENCE_AUTHORS };
int[] groupTo = new int[] { R.id.row_item_title, R.id.row_item_content, R.id.row_item_author, R.id.row_item_date, R.id.row_item_sidebar };
adapter = new FeedItemsAdapter(getActivity(), feed, R.layout.row_item, cursor, groupFrom, groupTo, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
adapter.setViewBinder(new FeedItemViewBinder(getActivity()));
itemList.setAdapter(adapter);
itemList.setOnItemClickListener(this);
itemList.setOnCreateContextMenuListener(this);
}
super.onLoadFinished(loader, cursor);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (getActivity().isFinishing()) return;
Intent i = new Intent(getActivity(), FeedReading.class);
i.putExtra(Reading.EXTRA_FEEDSET, getFeedSet());
i.putExtra(Reading.EXTRA_FEED, feedId);
i.putExtra(Reading.EXTRA_FEED, feed.feedId);
i.putExtra(FeedReading.EXTRA_POSITION, position);
i.putExtra(ItemsList.EXTRA_STATE, currentState);
i.putExtra(Reading.EXTRA_DEFAULT_FEED_VIEW, defaultFeedView);

View file

@ -183,14 +183,13 @@ public class FolderListFragment extends NbFragment implements OnGroupClickListen
int groupPosition = ExpandableListView.getPackedPositionGroup(info.packedPosition);
if (item.getItemId() == R.id.menu_delete_feed) {
String feedName;
if (groupPosition == 0) {
feedName = adapter.getSocialFeed(adapter.getChild(groupPosition, childPosition)).feedTitle;
} else {
feedName = adapter.getFeed(adapter.getChild(groupPosition, childPosition)).title;
}
String folderName = adapter.getGroup(groupPosition);
DialogFragment deleteFeedFragment = DeleteFeedFragment.newInstance(info.id, feedName, folderName);
DialogFragment deleteFeedFragment;
if (groupPosition == 0) {
deleteFeedFragment = DeleteFeedFragment.newInstance(adapter.getSocialFeed(adapter.getChild(groupPosition, childPosition)), folderName);
} else {
deleteFeedFragment = DeleteFeedFragment.newInstance(adapter.getFeed(adapter.getChild(groupPosition, childPosition)), folderName);
}
deleteFeedFragment.show(getFragmentManager(), "dialog");
return true;
} else if (item.getItemId() == R.id.menu_mark_feed_as_read) {
@ -259,8 +258,7 @@ public class FolderListFragment extends NbFragment implements OnGroupClickListen
Feed feed = adapter.getFeed(childName);
String folderName = adapter.getGroup(groupPosition);
Intent intent = new Intent(getActivity(), FeedItemsList.class);
intent.putExtra(FeedItemsList.EXTRA_FEED, feed.feedId);
intent.putExtra(FeedItemsList.EXTRA_FEED_TITLE, feed.title);
intent.putExtra(FeedItemsList.EXTRA_FEED, feed);
intent.putExtra(FeedItemsList.EXTRA_FOLDER_NAME, folderName);
intent.putExtra(ItemsList.EXTRA_STATE, currentState);
getActivity().startActivity(intent);

View file

@ -502,9 +502,9 @@ public class APIManager {
}
}
public NewsBlurResponse deleteFeed(long feedId, String folderName) {
public NewsBlurResponse deleteFeed(String feedId, String folderName) {
ContentValues values = new ContentValues();
values.put(APIConstants.PARAMETER_FEEDID, Long.toString(feedId));
values.put(APIConstants.PARAMETER_FEEDID, feedId);
if ((!TextUtils.isEmpty(folderName)) && (!folderName.equals(AppConstants.ROOT_FOLDER))) {
values.put(APIConstants.PARAMETER_IN_FOLDER, folderName);
}

View file

@ -68,7 +68,7 @@ public class FeedUtils {
}.execute();
}
public static void deleteFeed(final long feedId, final String folderName, final Context context, final APIManager apiManager) {
public static void deleteFeed(final String feedId, final String folderName, final Context context, final APIManager apiManager) {
new AsyncTask<Void, Void, NewsBlurResponse>() {
@Override
protected NewsBlurResponse doInBackground(Void... arg) {
@ -77,7 +77,7 @@ public class FeedUtils {
@Override
protected void onPostExecute(NewsBlurResponse result) {
// TODO: we can't check result.isError() because the delete call sets the .message property on all calls. find a better error check
dbHelper.deleteFeed(Long.toString(feedId));
dbHelper.deleteFeed(feedId);
NbActivity.updateAllActivities();
Toast.makeText(context, R.string.toast_feed_deleted, Toast.LENGTH_SHORT).show();
}