Merge pull request #615 from dosiecki/master

Android: Bugfixes and Speed
This commit is contained in:
Samuel Clay 2014-11-12 15:27:28 -08:00
commit 5d5709f28a
22 changed files with 154 additions and 303 deletions

View file

@ -2,7 +2,7 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/selector_feed_background" >
style="?selectorFeedBackground" >
<LinearLayout
android:id="@+id/row_foldersums"
@ -63,7 +63,7 @@
android:textStyle="bold"
android:layout_toLeftOf="@id/row_foldersums"
android:layout_toRightOf="@id/row_socialfeed_icon"
android:textColor="@color/folder_text"
style="?selectorRowFeedName"
android:paddingBottom="7dp"
android:paddingTop="7dp"
android:textSize="14dp" />

View file

@ -69,10 +69,6 @@ public class NbActivity extends Activity {
synchronized (AllActivities) {
AllActivities.add(this);
}
// ensure that the sync service is up and running at the beginning of every activity, since
// FeedUtils needs the DB conn it provides
triggerSync();
}
@Override

View file

@ -7,6 +7,7 @@ import android.database.Cursor;
import static android.database.DatabaseUtils.dumpCursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.os.CancellationSignal;
import android.text.TextUtils;
import android.util.Log;
@ -419,7 +420,7 @@ public class BlurDatabaseHelper {
}
public int getUnreadCount(FeedSet fs, StateFilter stateFilter) {
Cursor c = getStoriesCursor(fs, stateFilter, ReadFilter.PURE_UNREAD, null);
Cursor c = getStoriesCursor(fs, stateFilter, ReadFilter.PURE_UNREAD, null, null);
int count = c.getCount();
c.close();
return count;
@ -493,32 +494,32 @@ public class BlurDatabaseHelper {
public Loader<Cursor> getSocialFeedsLoader(final StateFilter stateFilter) {
return new QueryCursorLoader(context) {
protected Cursor createCursor() {return getSocialFeedsCursor(stateFilter);}
protected Cursor createCursor() {return getSocialFeedsCursor(stateFilter, cancellationSignal);}
};
}
public Cursor getSocialFeedsCursor(StateFilter stateFilter) {
return dbRO.query(DatabaseConstants.SOCIALFEED_TABLE, null, DatabaseConstants.getBlogSelectionFromState(stateFilter), null, null, null, "UPPER(" + DatabaseConstants.SOCIAL_FEED_TITLE + ") ASC");
public Cursor getSocialFeedsCursor(StateFilter stateFilter, CancellationSignal cancellationSignal) {
return dbRO.query(false, DatabaseConstants.SOCIALFEED_TABLE, null, DatabaseConstants.getBlogSelectionFromState(stateFilter), null, null, null, "UPPER(" + DatabaseConstants.SOCIAL_FEED_TITLE + ") ASC", null, cancellationSignal);
}
public Loader<Cursor> getFolderFeedMapLoader() {
return new QueryCursorLoader(context) {
protected Cursor createCursor() {return getFolderFeedMapCursor();}
protected Cursor createCursor() {return getFolderFeedMapCursor(cancellationSignal);}
};
}
public Cursor getFolderFeedMapCursor() {
return dbRO.query(DatabaseConstants.FEED_FOLDER_MAP_TABLE, null, null, null, null, null, null);
public Cursor getFolderFeedMapCursor(CancellationSignal cancellationSignal) {
return dbRO.query(false, DatabaseConstants.FEED_FOLDER_MAP_TABLE, null, null, null, null, null, null, null, cancellationSignal);
}
public Loader<Cursor> getFeedsLoader(final StateFilter stateFilter) {
return new QueryCursorLoader(context) {
protected Cursor createCursor() {return getFeedsCursor(stateFilter);}
protected Cursor createCursor() {return getFeedsCursor(stateFilter, cancellationSignal);}
};
}
public Cursor getFeedsCursor(StateFilter stateFilter) {
return dbRO.query(DatabaseConstants.FEED_TABLE, null, DatabaseConstants.getFeedSelectionFromState(stateFilter), null, null, null, "UPPER(" + DatabaseConstants.FEED_TITLE + ") ASC");
public Cursor getFeedsCursor(StateFilter stateFilter, CancellationSignal cancellationSignal) {
return dbRO.query(false, DatabaseConstants.FEED_TABLE, null, DatabaseConstants.getFeedSelectionFromState(stateFilter), null, null, null, "UPPER(" + DatabaseConstants.FEED_TITLE + ") ASC", null, cancellationSignal);
}
public Loader<Cursor> getSavedStoryCountLoader() {
@ -533,17 +534,17 @@ public class BlurDatabaseHelper {
public Loader<Cursor> getStoriesLoader(final FeedSet fs, final StateFilter stateFilter) {
return new QueryCursorLoader(context) {
protected Cursor createCursor() {return getStoriesCursor(fs, stateFilter);}
protected Cursor createCursor() {return getStoriesCursor(fs, stateFilter, cancellationSignal);}
};
}
public Cursor getStoriesCursor(FeedSet fs, StateFilter stateFilter) {
public Cursor getStoriesCursor(FeedSet fs, StateFilter stateFilter, CancellationSignal cancellationSignal) {
ReadFilter readFilter = PrefsUtils.getReadFilter(context, fs);
StoryOrder order = PrefsUtils.getStoryOrder(context, fs);
return getStoriesCursor(fs, stateFilter, readFilter, order);
return getStoriesCursor(fs, stateFilter, readFilter, order, cancellationSignal);
}
public Cursor getStoriesCursor(FeedSet fs, StateFilter stateFilter, ReadFilter readFilter, StoryOrder order) {
private Cursor getStoriesCursor(FeedSet fs, StateFilter stateFilter, ReadFilter readFilter, StoryOrder order, CancellationSignal cancellationSignal) {
if (fs.getSingleFeed() != null) {
@ -552,7 +553,7 @@ public class BlurDatabaseHelper {
q.append(" FROM " + DatabaseConstants.STORY_TABLE);
q.append(" WHERE " + DatabaseConstants.STORY_FEED_ID + " = ?");
DatabaseConstants.appendStorySelectionGroupOrder(q, readFilter, order, stateFilter, null);
return dbRO.rawQuery(q.toString(), new String[]{fs.getSingleFeed()});
return dbRO.rawQuery(q.toString(), new String[]{fs.getSingleFeed()}, cancellationSignal);
} else if (fs.getMultipleFeeds() != null) {
@ -562,7 +563,7 @@ public class BlurDatabaseHelper {
q.append(" WHERE " + DatabaseConstants.STORY_TABLE + "." + DatabaseConstants.STORY_FEED_ID + " IN ( ");
q.append(TextUtils.join(",", fs.getMultipleFeeds()) + ")");
DatabaseConstants.appendStorySelectionGroupOrder(q, readFilter, order, stateFilter, null);
return dbRO.rawQuery(q.toString(), null);
return dbRO.rawQuery(q.toString(), null, cancellationSignal);
} else if (fs.getSingleSocialFeed() != null) {
@ -572,7 +573,7 @@ public class BlurDatabaseHelper {
q.append(DatabaseConstants.JOIN_FEEDS_ON_STORIES);
q.append(" WHERE " + DatabaseConstants.SOCIALFEED_STORY_MAP_TABLE + "." + DatabaseConstants.SOCIALFEED_STORY_USER_ID + " = ? ");
DatabaseConstants.appendStorySelectionGroupOrder(q, readFilter, order, stateFilter, null);
return dbRO.rawQuery(q.toString(), new String[]{fs.getSingleSocialFeed().getKey()});
return dbRO.rawQuery(q.toString(), new String[]{fs.getSingleSocialFeed().getKey()}, cancellationSignal);
} else if (fs.isAllNormal()) {
@ -581,7 +582,7 @@ public class BlurDatabaseHelper {
q.append(DatabaseConstants.JOIN_FEEDS_ON_STORIES);
q.append(" WHERE 1");
DatabaseConstants.appendStorySelectionGroupOrder(q, readFilter, order, stateFilter, null);
return dbRO.rawQuery(q.toString(), null);
return dbRO.rawQuery(q.toString(), null, cancellationSignal);
} else if (fs.isAllSocial()) {
@ -590,7 +591,7 @@ public class BlurDatabaseHelper {
q.append(DatabaseConstants.JOIN_STORIES_ON_SOCIALFEED_MAP);
q.append(DatabaseConstants.JOIN_FEEDS_ON_STORIES);
DatabaseConstants.appendStorySelectionGroupOrder(q, readFilter, order, stateFilter, DatabaseConstants.STORY_TABLE + "." + DatabaseConstants.STORY_ID);
return dbRO.rawQuery(q.toString(), null);
return dbRO.rawQuery(q.toString(), null, cancellationSignal);
} else if (fs.isAllSaved()) {
@ -600,7 +601,7 @@ public class BlurDatabaseHelper {
q.append(" WHERE ((" + DatabaseConstants.STORY_STARRED + " = 1)");
q.append(" OR (" + DatabaseConstants.STORY_READ_THIS_SESSION + " = 1))");
q.append(" ORDER BY " + DatabaseConstants.STARRED_STORY_ORDER);
return dbRO.rawQuery(q.toString(), null);
return dbRO.rawQuery(q.toString(), null, cancellationSignal);
} else {
throw new IllegalStateException("Asked to get stories for FeedSet of unknown type.");

View file

@ -290,7 +290,7 @@ public class DatabaseConstants {
REPLY_COMMENTID, REPLY_DATE, REPLY_ID, REPLY_SHORTDATE, REPLY_TEXT, REPLY_USERID
};
private static final String SUM_STORY_TOTAL = "storyTotal";
public static final String SUM_STORY_TOTAL = "storyTotal";
private static String STORY_SUM_TOTAL = " CASE " +
"WHEN MAX(" + STORY_INTELLIGENCE_AUTHORS + "," + STORY_INTELLIGENCE_TAGS + "," + STORY_INTELLIGENCE_TITLE + ") > 0 " +
"THEN MAX(" + STORY_INTELLIGENCE_AUTHORS + "," + STORY_INTELLIGENCE_TAGS + "," + STORY_INTELLIGENCE_TITLE + ") " +

View file

@ -24,8 +24,8 @@ public class FeedItemsAdapter extends StoryItemsAdapter {
private final Feed feed;
private int storyTitleUnread, storyTitleRead, storyContentUnread, storyContentRead, storyAuthorUnread, storyAuthorRead, storyDateUnread, storyDateRead;
public FeedItemsAdapter(Context context, Feed feed, int layout, Cursor c, String[] from, int[] to, int flags) {
super(context, layout, c, from, to, flags);
public FeedItemsAdapter(Context context, Feed feed, int layout, Cursor c, String[] from, int[] to) {
super(context, layout, c, from, to);
this.feed = feed;
this.cursor = c;

View file

@ -307,7 +307,7 @@ public class FolderListAdapter extends BaseExpandableListAdapter {
}
public synchronized void setFeedCursor(Cursor cursor) {
if ((cursor.getCount() < 1) || (!cursor.isBeforeFirst())) return;
if (!cursor.isBeforeFirst()) return;
feeds = new LinkedHashMap<String,Feed>(cursor.getCount());
while (cursor.moveToNext()) {
Feed f = Feed.fromCursor(cursor);
@ -326,6 +326,7 @@ public class FolderListAdapter extends BaseExpandableListAdapter {
}
private void recountFeeds() {
if ((folderFeedMap == null) || (feeds == null)) return;
int c = folderFeedMap.keySet().size();
activeFolderNames = new ArrayList<String>(c);
activeFolderChildren = new ArrayList<List<Feed>>(c);

View file

@ -26,8 +26,8 @@ public class MultipleFeedItemsAdapter extends StoryItemsAdapter {
private int storyTitleUnread, storyContentUnread, storyAuthorUnread, storyTitleRead, storyContentRead, storyAuthorRead, storyDateUnread, storyDateRead, storyFeedUnread, storyFeedRead;
private boolean ignoreReadStatus;
public MultipleFeedItemsAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags, boolean ignoreReadStatus) {
super(context, layout, c, from, to, flags);
public MultipleFeedItemsAdapter(Context context, int layout, Cursor c, String[] from, int[] to, boolean ignoreReadStatus) {
super(context, layout, c, from, to);
imageLoader = ((NewsBlurApplication) context.getApplicationContext()).getImageLoader();
this.cursor = c;
@ -45,8 +45,8 @@ public class MultipleFeedItemsAdapter extends StoryItemsAdapter {
this.ignoreReadStatus = ignoreReadStatus;
}
public MultipleFeedItemsAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
this(context, layout, c, from, to, flags, false);
public MultipleFeedItemsAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
this(context, layout, c, from, to, false);
}
@Override

View file

@ -15,7 +15,7 @@ import android.os.OperationCanceledException;
public abstract class QueryCursorLoader extends AsyncTaskLoader<Cursor> {
private Cursor cursor;
private CancellationSignal cancellationSignal;
protected CancellationSignal cancellationSignal;
public QueryCursorLoader(Context context) {
super(context);

View file

@ -10,8 +10,9 @@ import com.newsblur.domain.Story;
public abstract class StoryItemsAdapter extends SimpleCursorAdapter {
public StoryItemsAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
super(context, layout, c, from, to, flags);
public StoryItemsAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
// don't set *any* flags, we use auto-refreshing Loaders or plain Loaders and an explict load after syncs
super(context, layout, c, from, to, 0);
}
public abstract Story getStory(int position);

View file

@ -173,23 +173,6 @@ public class Story implements Serializable {
@SerializedName("title")
public int intelligenceTitle = 0;
}
public static int getIntelligenceTotal(int title, int authors, int tags, int feed) {
int score = 0;
List<Integer> list = Arrays.asList(title, authors, tags);
int max = Collections.max(list);
int min = Collections.min(list);
if (max > 0) {
score = max;
} else if (min < 0) {
score = min;
} else {
score = feed;
}
return score;
}
/**
* Custom equality based on storyID/feedID equality so that a Set can de-duplicate story objects.

View file

@ -4,15 +4,8 @@ import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import com.newsblur.R;
import com.newsblur.activity.AllSharedStoriesReading;
@ -26,33 +19,14 @@ import com.newsblur.util.StateFilter;
import com.newsblur.util.StoryOrder;
import com.newsblur.view.SocialItemViewBinder;
public class AllSharedStoriesItemListFragment extends ItemListFragment implements OnItemClickListener {
ListView itemList;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_itemlist, null);
itemList = (ListView) v.findViewById(R.id.itemlistfragment_list);
setupBezelSwipeDetector(itemList);
itemList.setEmptyView(v.findViewById(R.id.empty_view));
itemList.setOnScrollListener(this);
itemList.setOnItemClickListener(this);
if (adapter != null) {
itemList.setAdapter(adapter);
}
getLoaderManager().initLoader(ITEMLIST_LOADER , null, this);
return v;
}
public class AllSharedStoriesItemListFragment extends ItemListFragment {
@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, DatabaseConstants.FEED_TITLE };
String[] groupFrom = new String[] { DatabaseConstants.STORY_TITLE, DatabaseConstants.STORY_SHORT_CONTENT, DatabaseConstants.STORY_AUTHORS, DatabaseConstants.STORY_TIMESTAMP, DatabaseConstants.SUM_STORY_TOTAL, DatabaseConstants.FEED_TITLE };
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, R.id.row_item_feedtitle };
adapter = new MultipleFeedItemsAdapter(getActivity(), R.layout.row_socialitem, cursor, groupFrom, groupTo, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
adapter = new MultipleFeedItemsAdapter(getActivity(), R.layout.row_socialitem, cursor, groupFrom, groupTo);
adapter.setViewBinder(new SocialItemViewBinder(getActivity()));
itemList.setAdapter(adapter);
}

View file

@ -3,15 +3,9 @@ package com.newsblur.fragment;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.content.CursorLoader;
import android.content.Loader;
import android.widget.CursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import com.newsblur.R;
import com.newsblur.activity.AllStoriesReading;
@ -25,34 +19,14 @@ import com.newsblur.util.StateFilter;
import com.newsblur.util.StoryOrder;
import com.newsblur.view.SocialItemViewBinder;
public class AllStoriesItemListFragment extends ItemListFragment implements OnItemClickListener {
private ListView itemList;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_itemlist, null);
itemList = (ListView) v.findViewById(R.id.itemlistfragment_list);
setupBezelSwipeDetector(itemList);
itemList.setEmptyView(v.findViewById(R.id.empty_view));
itemList.setOnScrollListener(this);
itemList.setOnItemClickListener(this);
itemList.setOnCreateContextMenuListener(this);
if (adapter != null) {
itemList.setAdapter(adapter);
}
getLoaderManager().initLoader(ITEMLIST_LOADER , null, this);
return v;
}
public class AllStoriesItemListFragment extends ItemListFragment {
@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, DatabaseConstants.FEED_TITLE };
String[] groupFrom = new String[] { DatabaseConstants.STORY_TITLE, DatabaseConstants.STORY_SHORT_CONTENT, DatabaseConstants.STORY_AUTHORS, DatabaseConstants.STORY_TIMESTAMP, DatabaseConstants.SUM_STORY_TOTAL, DatabaseConstants.FEED_TITLE };
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, R.id.row_item_feedtitle };
adapter = new MultipleFeedItemsAdapter(getActivity(), R.layout.row_socialitem, cursor, groupFrom, groupTo, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
adapter = new MultipleFeedItemsAdapter(getActivity(), R.layout.row_socialitem, cursor, groupFrom, groupTo);
adapter.setViewBinder(new SocialItemViewBinder(getActivity()));
itemList.setAdapter(adapter);
}

View file

@ -1,20 +1,11 @@
package com.newsblur.fragment;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.content.CursorLoader;
import android.content.Loader;
import android.widget.CursorAdapter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import com.newsblur.R;
import com.newsblur.activity.FeedReading;
@ -29,10 +20,9 @@ import com.newsblur.util.StoryOrder;
import com.newsblur.util.ReadFilter;
import com.newsblur.view.FeedItemViewBinder;
public class FeedItemListFragment extends ItemListFragment implements OnItemClickListener {
public class FeedItemListFragment extends ItemListFragment {
private Feed feed;
private ListView itemList;
public static FeedItemListFragment newInstance(Feed feed, StateFilter currentState, DefaultFeedView defaultFeedView) {
FeedItemListFragment feedItemFragment = new FeedItemListFragment();
@ -52,33 +42,12 @@ public class FeedItemListFragment extends ItemListFragment implements OnItemClic
feed = (Feed) getArguments().getSerializable("feed");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_itemlist, null);
itemList = (ListView) v.findViewById(R.id.itemlistfragment_list);
setupBezelSwipeDetector(itemList);
itemList.setEmptyView(v.findViewById(R.id.empty_view));
itemList.setOnItemClickListener(this);
itemList.setOnCreateContextMenuListener(this);
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);
}
getLoaderManager().initLoader(ITEMLIST_LOADER , null, 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 };
String[] groupFrom = new String[] { DatabaseConstants.STORY_TITLE, DatabaseConstants.STORY_SHORT_CONTENT, DatabaseConstants.STORY_AUTHORS, DatabaseConstants.STORY_TIMESTAMP, DatabaseConstants.SUM_STORY_TOTAL };
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 = new FeedItemsAdapter(getActivity(), feed, R.layout.row_item, cursor, groupFrom, groupTo);
adapter.setViewBinder(new FeedItemViewBinder(getActivity()));
itemList.setAdapter(adapter);
}

View file

@ -1,19 +1,11 @@
package com.newsblur.fragment;
import java.util.ArrayList;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.content.CursorLoader;
import android.content.Loader;
import android.widget.CursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import com.newsblur.R;
import com.newsblur.activity.FeedReading;
@ -27,7 +19,7 @@ import com.newsblur.util.StateFilter;
import com.newsblur.util.StoryOrder;
import com.newsblur.view.FeedItemViewBinder;
public class FolderItemListFragment extends ItemListFragment implements OnItemClickListener {
public class FolderItemListFragment extends ItemListFragment {
private String folderName;
@ -49,33 +41,17 @@ public class FolderItemListFragment extends ItemListFragment implements OnItemCl
folderName = getArguments().getString("folderName");
}
@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);
setupBezelSwipeDetector(itemList);
itemList.setEmptyView(v.findViewById(R.id.empty_view));
Cursor cursor = dbHelper.getStoriesCursor(getFeedSet(), currentState);
getActivity().startManagingCursor(cursor);
String[] groupFrom = new String[] { DatabaseConstants.STORY_TITLE, DatabaseConstants.STORY_SHORT_CONTENT, DatabaseConstants.FEED_TITLE, DatabaseConstants.STORY_TIMESTAMP, DatabaseConstants.STORY_INTELLIGENCE_AUTHORS, DatabaseConstants.STORY_AUTHORS };
int[] groupTo = new int[] { R.id.row_item_title, R.id.row_item_content, R.id.row_item_feedtitle, R.id.row_item_date, R.id.row_item_sidebar, R.id.row_item_author };
getLoaderManager().initLoader(ITEMLIST_LOADER , null, this);
adapter = new MultipleFeedItemsAdapter(getActivity(), R.layout.row_folderitem, cursor, groupFrom, groupTo, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
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.FEED_TITLE, DatabaseConstants.STORY_TIMESTAMP, DatabaseConstants.SUM_STORY_TOTAL, DatabaseConstants.STORY_AUTHORS };
int[] groupTo = new int[] { R.id.row_item_title, R.id.row_item_content, R.id.row_item_feedtitle, R.id.row_item_date, R.id.row_item_sidebar, R.id.row_item_author };
adapter = new MultipleFeedItemsAdapter(getActivity(), R.layout.row_folderitem, cursor, groupFrom, groupTo);
adapter.setViewBinder(new FeedItemViewBinder(getActivity()));
itemList.setAdapter(adapter);
}
super.onLoadFinished(loader, cursor);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

View file

@ -59,13 +59,15 @@ public class FolderListFragment extends NbFragment implements OnGroupClickListen
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
public synchronized void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
sharedPreferences = getActivity().getSharedPreferences(PrefConstants.PREFERENCES, 0);
getLoaderManager().initLoader(SOCIALFEEDS_LOADER, null, this);
getLoaderManager().initLoader(FOLDERFEEDMAP_LOADER, null, this);
getLoaderManager().initLoader(FEEDS_LOADER, null, this);
getLoaderManager().initLoader(SAVEDCOUNT_LOADER, null, this);
if (getLoaderManager().getLoader(FOLDERFEEDMAP_LOADER) == null) {
getLoaderManager().initLoader(SOCIALFEEDS_LOADER, null, this);
getLoaderManager().initLoader(FOLDERFEEDMAP_LOADER, null, this);
getLoaderManager().initLoader(FEEDS_LOADER, null, this);
getLoaderManager().initLoader(SAVEDCOUNT_LOADER, null, this);
}
}
@Override
@ -107,7 +109,7 @@ public class FolderListFragment extends NbFragment implements OnGroupClickListen
@Override
public void onLoaderReset(Loader<Cursor> loader) {
;
; // our adapter doesn't hold on to cursors
}
public void hasUpdated() {
@ -193,8 +195,13 @@ public class FolderListFragment extends NbFragment implements OnGroupClickListen
deleteFeedFragment.show(getFragmentManager(), "dialog");
return true;
} else if (item.getItemId() == R.id.menu_mark_feed_as_read) {
FeedUtils.markFeedsRead(FeedSet.singleFeed(Long.toString(info.id)), null, null, getActivity());
adapter.notifyDataSetChanged();
String feedId = adapter.getChild(groupPosition, childPosition);
if (groupPosition == 0) {
SocialFeed socialFeed = adapter.getSocialFeed(feedId);
FeedUtils.markFeedsRead(FeedSet.singleSocialFeed(socialFeed.userId, socialFeed.username), null, null, getActivity());
} else {
FeedUtils.markFeedsRead(FeedSet.singleFeed(feedId), null, null, getActivity());
}
return true;
} else if (item.getItemId() == R.id.menu_mark_folder_as_read) {
if (!adapter.isFolderRoot(groupPosition)) {
@ -203,7 +210,6 @@ public class FolderListFragment extends NbFragment implements OnGroupClickListen
} else {
FeedUtils.markFeedsRead(FeedSet.allFeeds(), null, null, getActivity());
}
adapter.notifyDataSetChanged();
return true;
}

View file

@ -8,6 +8,7 @@ import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
@ -15,9 +16,11 @@ import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnCreateContextMenuListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.TextView;
@ -30,11 +33,12 @@ import com.newsblur.util.FeedSet;
import com.newsblur.util.FeedUtils;
import com.newsblur.util.StateFilter;
public abstract class ItemListFragment extends NbFragment implements OnScrollListener, OnCreateContextMenuListener, LoaderManager.LoaderCallbacks<Cursor> {
public abstract class ItemListFragment extends NbFragment implements OnScrollListener, OnCreateContextMenuListener, LoaderManager.LoaderCallbacks<Cursor>, OnItemClickListener {
public static int ITEMLIST_LOADER = 0x01;
protected ItemsList activity;
protected ListView itemList;
protected StoryItemsAdapter adapter;
protected DefaultFeedView defaultFeedView;
protected StateFilter currentState;
@ -49,6 +53,31 @@ public abstract class ItemListFragment extends NbFragment implements OnScrollLis
activity = (ItemsList) getActivity();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_itemlist, null);
itemList = (ListView) v.findViewById(R.id.itemlistfragment_list);
setupBezelSwipeDetector(itemList);
itemList.setEmptyView(v.findViewById(R.id.empty_view));
itemList.setOnScrollListener(this);
itemList.setOnItemClickListener(this);
itemList.setOnCreateContextMenuListener(this);
if (adapter != null) {
// normally the adapter is set when it is created in onLoadFinished(), but sometimes
// onCreateView gets re-called thereafter.
itemList.setAdapter(adapter);
}
return v;
}
@Override
public synchronized void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (getLoaderManager().getLoader(ITEMLIST_LOADER) == null) {
getLoaderManager().initLoader(ITEMLIST_LOADER, null, this);
}
}
/**
* Indicate that the DB was cleared.
*/
@ -94,10 +123,13 @@ public abstract class ItemListFragment extends NbFragment implements OnScrollLis
@Override
public synchronized void onScroll(AbsListView view, int firstVisible, int visibleCount, int totalCount) {
// load an extra page or two worth of stories past the viewport
int desiredStoryCount = firstVisible + (visibleCount*2) + 1;
activity.triggerRefresh(desiredStoryCount, totalCount);
// if we have seen a cursor, this method means the list was updated or scrolled. now is a good
// time to see if we need more stories
if (cursorSeenYet) {
// load an extra page or two worth of stories past the viewport
int desiredStoryCount = firstVisible + (visibleCount*2) + 1;
activity.triggerRefresh(desiredStoryCount, totalCount);
}
}
@Override
@ -172,22 +204,18 @@ public abstract class ItemListFragment extends NbFragment implements OnScrollLis
switch (item.getItemId()) {
case R.id.menu_mark_story_as_read:
FeedUtils.markStoryAsRead(story, activity);
hasUpdated();
return true;
case R.id.menu_mark_story_as_unread:
FeedUtils.markStoryUnread(story, activity);
hasUpdated();
return true;
case R.id.menu_mark_older_stories_as_read:
FeedUtils.markFeedsRead(getFeedSet(), story.timestamp, null, activity);
hasUpdated();
return true;
case R.id.menu_mark_newer_stories_as_read:
FeedUtils.markFeedsRead(getFeedSet(), null, story.timestamp, activity);
hasUpdated();
return true;
case R.id.menu_shared:
@ -208,6 +236,9 @@ public abstract class ItemListFragment extends NbFragment implements OnScrollLis
}
}
@Override
public abstract void onItemClick(AdapterView<?> parent, View view, int position, long id);
protected void setupBezelSwipeDetector(View v) {
final GestureDetector gestureDetector = new GestureDetector(getActivity(), new BezelSwipeDetector());
v.setOnTouchListener(new OnTouchListener() {

View file

@ -5,14 +5,10 @@ import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import com.newsblur.R;
import com.newsblur.activity.Reading;
@ -24,39 +20,13 @@ import com.newsblur.util.DefaultFeedView;
import com.newsblur.util.StoryOrder;
import com.newsblur.view.SocialItemViewBinder;
public class SavedStoriesItemListFragment extends ItemListFragment implements OnItemClickListener {
public class SavedStoriesItemListFragment extends ItemListFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@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);
setupBezelSwipeDetector(itemList);
itemList.setEmptyView(v.findViewById(R.id.empty_view));
Cursor cursor = dbHelper.getStoriesCursor(getFeedSet(), currentState);
String[] groupFrom = new String[] { DatabaseConstants.STORY_TITLE, DatabaseConstants.STORY_SHORT_CONTENT, DatabaseConstants.STORY_AUTHORS, DatabaseConstants.STORY_TIMESTAMP, DatabaseConstants.STORY_INTELLIGENCE_AUTHORS, DatabaseConstants.FEED_TITLE };
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, R.id.row_item_feedtitle };
getLoaderManager().initLoader(ITEMLIST_LOADER , null, this);
adapter = new MultipleFeedItemsAdapter(getActivity(), R.layout.row_socialitem, cursor, groupFrom, groupTo, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER, true);
itemList.setOnScrollListener(this);
adapter.setViewBinder(new SocialItemViewBinder(getActivity(), true));
itemList.setAdapter(adapter);
itemList.setOnItemClickListener(this);
return v;
}
public static ItemListFragment newInstance(DefaultFeedView defaultFeedView) {
ItemListFragment fragment = new SavedStoriesItemListFragment();
Bundle args = new Bundle();
@ -65,6 +35,18 @@ public class SavedStoriesItemListFragment extends ItemListFragment implements On
return fragment;
}
@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.SUM_STORY_TOTAL, DatabaseConstants.FEED_TITLE };
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, R.id.row_item_feedtitle };
adapter = new MultipleFeedItemsAdapter(getActivity(), R.layout.row_socialitem, cursor, groupFrom, groupTo, true);
adapter.setViewBinder(new SocialItemViewBinder(getActivity(), true));
itemList.setAdapter(adapter);
}
super.onLoadFinished(loader, cursor);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (getActivity().isFinishing()) return;
@ -75,5 +57,13 @@ public class SavedStoriesItemListFragment extends ItemListFragment implements On
startActivity(i);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.removeItem(R.id.menu_mark_story_as_read);
menu.removeItem(R.id.menu_mark_story_as_unread);
menu.removeItem(R.id.menu_mark_newer_stories_as_read);
menu.removeItem(R.id.menu_mark_older_stories_as_read);
}
}

View file

@ -1,19 +1,11 @@
package com.newsblur.fragment;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import com.newsblur.R;
import com.newsblur.activity.ItemsList;
@ -27,10 +19,9 @@ import com.newsblur.util.StateFilter;
import com.newsblur.util.StoryOrder;
import com.newsblur.view.SocialItemViewBinder;
public class SocialFeedItemListFragment extends ItemListFragment implements OnItemClickListener {
public class SocialFeedItemListFragment extends ItemListFragment {
private SocialFeed socialFeed;
private ListView itemList;
@Override
public void onCreate(Bundle savedInstanceState) {
@ -49,27 +40,12 @@ public class SocialFeedItemListFragment extends ItemListFragment implements OnIt
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_itemlist, null);
itemList = (ListView) v.findViewById(R.id.itemlistfragment_list);
setupBezelSwipeDetector(itemList);
itemList.setEmptyView(v.findViewById(R.id.empty_view));
itemList.setOnScrollListener(this);
itemList.setOnItemClickListener(this);
if (adapter != null) {
itemList.setAdapter(adapter);
}
return v;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
if ((adapter == null) && (cursor != null)) {
String[] groupFroms = new String[] { DatabaseConstants.STORY_TITLE, DatabaseConstants.FEED_FAVICON_URL, DatabaseConstants.FEED_TITLE, DatabaseConstants.STORY_SHORT_CONTENT, DatabaseConstants.STORY_TIMESTAMP, DatabaseConstants.STORY_AUTHORS, DatabaseConstants.STORY_INTELLIGENCE_AUTHORS};
String[] groupFroms = new String[] { DatabaseConstants.STORY_TITLE, DatabaseConstants.FEED_FAVICON_URL, DatabaseConstants.FEED_TITLE, DatabaseConstants.STORY_SHORT_CONTENT, DatabaseConstants.STORY_TIMESTAMP, DatabaseConstants.STORY_AUTHORS, DatabaseConstants.SUM_STORY_TOTAL};
int[] groupTos = new int[] { R.id.row_item_title, R.id.row_item_feedicon, R.id.row_item_feedtitle, R.id.row_item_content, R.id.row_item_date, R.id.row_item_author, R.id.row_item_sidebar};
adapter = new MultipleFeedItemsAdapter(getActivity(), R.layout.row_socialitem, cursor, groupFroms, groupTos, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
adapter = new MultipleFeedItemsAdapter(getActivity(), R.layout.row_socialitem, cursor, groupFroms, groupTos);
adapter.setViewBinder(new SocialItemViewBinder(getActivity()));
itemList.setAdapter(adapter);
}

View file

@ -7,6 +7,7 @@ import android.content.Intent;
import android.database.Cursor;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.Process;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
@ -145,6 +146,7 @@ public class NBSyncService extends Service {
// allowed to do tangible work. We spawn a thread to do so.
Runnable r = new Runnable() {
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
doSync(startId);
}
};
@ -259,23 +261,12 @@ public class NBSyncService extends Service {
*/
private void finishActions() {
if (HaltNow) return;
if (FollowupActions.size() < 1) return;
try {
if (FollowupActions.size() < 1) return;
ActionsRunning = true;
NbActivity.updateAllActivities();
for (ReadingAction ra : FollowupActions) {
ra.doLocal(dbHelper);
}
FollowupActions.clear();
} finally {
if (ActionsRunning) {
ActionsRunning = false;
NbActivity.updateAllActivities();
}
for (ReadingAction ra : FollowupActions) {
ra.doLocal(dbHelper);
}
FollowupActions.clear();
}
/**
@ -676,7 +667,6 @@ public class NBSyncService extends Service {
*/
public static void forceFeedsFolders() {
DoFeedsFolders = true;
NbActivity.updateAllActivities();
}
/**

View file

@ -106,7 +106,7 @@ public class FeedUtils {
setStoryReadState(story, context, false);
return null;
}
}.execute();
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public static void markStoryAsRead(final Story story, final Context context) {
@ -116,7 +116,7 @@ public class FeedUtils {
setStoryReadState(story, context, true);
return null;
}
}.execute();
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private static void setStoryReadState(Story story, Context context, boolean read) {
@ -146,12 +146,13 @@ public class FeedUtils {
FeedSet newFeedSet = FeedSet.folder("all", dbHelper.getAllFeeds());
ra = ReadingAction.markFeedRead(newFeedSet, olderThan, newerThan);
}
dbHelper.enqueueAction(ra);
dbHelper.markStoriesRead(fs, olderThan, newerThan);
NbActivity.updateAllActivities();
dbHelper.enqueueAction(ra);
triggerSync(context);
return null;
}
}.execute();
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public static void updateClassifier(final String feedId, final String key, final Classifier classifier, final int classifierType, final int classifierAction, final Context context) {
@ -219,12 +220,4 @@ public class FeedUtils {
return parts[0];
}
/**
* An interface usable by callers of this utility class that allows them to receive
* notification that the async methods here have finihed and may have updated the DB
* as a result.
*/
public interface ActionCompletionListener {
public abstract void actionCompleteCallback(boolean noMoreData);
}
}

View file

@ -6,6 +6,7 @@ import android.graphics.drawable.Drawable;
import android.widget.SimpleCursorAdapter.ViewBinder;
import android.text.Html;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
@ -48,13 +49,8 @@ public class FeedItemViewBinder implements ViewBinder {
((TextView) view).setText(cursor.getString(columnIndex).toUpperCase());
}
return true;
} else if (TextUtils.equals(columnName, DatabaseConstants.STORY_INTELLIGENCE_AUTHORS)) {
int authors = cursor.getInt(columnIndex);
int tags = cursor.getInt(cursor.getColumnIndex(DatabaseConstants.STORY_INTELLIGENCE_TAGS));
int feed = cursor.getInt(cursor.getColumnIndex(DatabaseConstants.STORY_INTELLIGENCE_FEED));
int title = cursor.getInt(cursor.getColumnIndex(DatabaseConstants.STORY_INTELLIGENCE_TITLE));
int score = Story.getIntelligenceTotal(title, authors, tags, feed);
} else if (TextUtils.equals(columnName, DatabaseConstants.SUM_STORY_TOTAL)) {
int score = cursor.getInt(columnIndex);
Drawable icon;
if (score > 0) {
icon = view.getResources().getDrawable(R.drawable.g_icn_focus);

View file

@ -43,15 +43,9 @@ public class SocialItemViewBinder implements ViewBinder {
String faviconUrl = cursor.getString(columnIndex);
imageLoader.displayImage(faviconUrl, ((ImageView) view), true);
return true;
} else if (TextUtils.equals(columnName, DatabaseConstants.STORY_INTELLIGENCE_AUTHORS)) {
} else if (TextUtils.equals(columnName, DatabaseConstants.SUM_STORY_TOTAL)) {
if (! this.ignoreIntel) {
int authors = cursor.getInt(columnIndex);
int tags = cursor.getInt(cursor.getColumnIndex(DatabaseConstants.STORY_INTELLIGENCE_TAGS));
int feed = cursor.getInt(cursor.getColumnIndex(DatabaseConstants.STORY_INTELLIGENCE_FEED));
int title = cursor.getInt(cursor.getColumnIndex(DatabaseConstants.STORY_INTELLIGENCE_TITLE));
int score = Story.getIntelligenceTotal(title, authors, tags, feed);
int score = cursor.getInt(columnIndex);
Drawable icon;
if (score > 0) {
icon = view.getResources().getDrawable(R.drawable.g_icn_focus);