Added comment DB structure. Added comment and shared-icons for reading items. Added refresh of feed counts on app start. Added ability to manually refresh feed counts (currently un-throttled.) Modified Imageloader to use UIDs as the storage mechanism (rather than urls) to reduce network calls when we have the userId but not their photoUrl.

This commit is contained in:
RyanBateman 2012-07-24 14:41:56 -04:00
parent c4714abf57
commit 6536bdf41e
21 changed files with 438 additions and 187 deletions

View file

@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<com.newsblur.view.NonfocusScrollview xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.newsblur"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
android:background="@color/white" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="9dp" >
@ -54,7 +55,6 @@
android:textSize="11dp"
android:textStyle="italic" />
<android.support.v7.widget.GridLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/reading_item_tags"
@ -78,8 +78,51 @@
<WebView
android:id="@+id/reading_webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none" />
<RelativeLayout
android:id="@+id/reading_shared_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone" >
<LinearLayout
android:id="@+id/reading_share_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/list_background"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="10dp" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:text="@string/reading_sharedby"
android:textColor="@color/white"
android:textSize="12dp"
android:textStyle="bold" />
<android.support.v7.widget.GridLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/reading_social_shareimages"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:columnCount="8"
app:useDefaultMargins="true" />
</LinearLayout>
<LinearLayout
android:id="@+id/reading_comment_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/reading_share_bar"
android:background="@color/white"
android:orientation="vertical" />
</RelativeLayout>
</LinearLayout>
</com.newsblur.view.NonfocusScrollview>

View file

@ -19,6 +19,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/row_item_sidebar"
android:maxLines="2"
android:textColor="@color/darkgray"
android:textSize="18dp" />
@ -38,8 +39,8 @@
android:layout_height="wrap_content"
android:layout_below="@id/row_item_title"
android:layout_marginTop="10dp"
android:layout_toRightOf="@id/row_item_sidebar"
android:layout_toLeftOf="@id/row_item_date"
android:layout_toRightOf="@id/row_item_sidebar"
android:textColor="@color/lightgray"
android:textSize="12dp" />

View file

@ -30,7 +30,10 @@
<string name="description_row_folder_icon">folder icon</string>
<string name="description_activity_icon">An icon illustrating the user\'s activity</string>
<string name="description_follow_button">Follow or unfollow a user</string>
<string name="description_comment_user">Comment user image</string>
<string name="reading_sharedby">SHARED BY: </string>
<string name="share" formatted="false">\"%s\" - %s (via Newsblur)</string>
<string name="profile">Profile</string>
@ -55,5 +58,4 @@
<string name="menu_original">View original</string>
<string name="menu_share">Share</string>
</resources>

View file

@ -1,38 +1,36 @@
package com.newsblur.activity;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.Window;
import com.newsblur.R;
import com.newsblur.database.FeedProvider;
import com.newsblur.domain.Feed;
import com.newsblur.domain.Story;
import com.newsblur.fragment.ItemListFragment;
import com.newsblur.service.DetachableResultReceiver;
import com.newsblur.service.DetachableResultReceiver.Receiver;
import com.newsblur.fragment.SyncUpdateFragment;
import com.newsblur.service.SyncService;
public class ItemsList extends SherlockFragmentActivity {
public class ItemsList extends SherlockFragmentActivity implements SyncUpdateFragment.SyncUpdateFragmentInterface {
public static final String EXTRA_FEED = "feedId";
private ItemListFragment itemListFragment;
private FragmentManager fragmentManager;
private final String FRAGMENT_TAG = "itemListFragment";
private SyncReadingUpdaterFragment syncFragment;
private SyncUpdateFragment syncFragment;
private String feedId;
private String TAG = "ItemsList";
@Override
protected void onCreate(Bundle bundle) {
requestWindowFeature(Window.FEATURE_PROGRESS);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
super.onCreate(bundle);
setContentView(R.layout.activity_itemslist);
fragmentManager = getSupportFragmentManager();
@ -54,20 +52,16 @@ public class ItemsList extends SherlockFragmentActivity {
listTransaction.commit();
}
syncFragment = (SyncReadingUpdaterFragment) fragmentManager.findFragmentByTag(SyncReadingUpdaterFragment.TAG);
syncFragment = (SyncUpdateFragment) fragmentManager.findFragmentByTag(SyncUpdateFragment.TAG);
if (syncFragment == null) {
syncFragment = new SyncReadingUpdaterFragment();
fragmentManager.beginTransaction().add(syncFragment, SyncReadingUpdaterFragment.TAG).commit();
syncFragment = new SyncUpdateFragment();
fragmentManager.beginTransaction().add(syncFragment, SyncUpdateFragment.TAG).commit();
triggerRefresh();
}
}
public void redrawUI() {
Log.d(TAG , "Redrawing UI");
itemListFragment.updated();
}
public void triggerRefresh() {
setSupportProgressBarIndeterminateVisibility(true);
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_FEED_UPDATE);
@ -75,47 +69,6 @@ public class ItemsList extends SherlockFragmentActivity {
startService(intent);
}
public static class SyncReadingUpdaterFragment extends Fragment implements Receiver {
public static final String TAG = "SyncReadingFragment";
private DetachableResultReceiver receiver;
public SyncReadingUpdaterFragment() {
receiver = new DetachableResultReceiver(new Handler());
receiver.setReceiver(this);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
Log.d(TAG, "Creating syncfragment");
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Log.d(TAG, "Attached");
}
@Override
public void onReceiverResult(int resultCode, Bundle resultData) {
switch (resultCode) {
case SyncService.STATUS_FINISHED:
Log.d(TAG, "Synchronisation finished.");
if (getActivity() != null) {
((ItemsList) getActivity()).redrawUI();
}
break;
case SyncService.STATUS_RUNNING:
Log.d(TAG, "Synchronisation running.");
break;
default:
Log.e(TAG, "Unrecognised response attempting to get reading data");
break;
}
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
@ -126,4 +79,18 @@ public class ItemsList extends SherlockFragmentActivity {
return false;
}
@Override
public void updateAfterSync() {
Log.d(TAG , "Redrawing UI");
itemListFragment.updated();
setSupportProgressBarIndeterminateVisibility(false);
}
@Override
public void updateSyncStatus(boolean syncRunning) {
if (syncRunning) {
setSupportProgressBarIndeterminateVisibility(true);
}
}
}

View file

@ -10,41 +10,70 @@ import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.Window;
import com.newsblur.R;
import com.newsblur.fragment.FolderFeedListFragment;
import com.newsblur.fragment.ItemListFragment;
import com.newsblur.fragment.SyncUpdateFragment;
import com.newsblur.network.domain.FeedFolderResponse;
import com.newsblur.service.SyncService;
import com.newsblur.view.StateToggleButton.StateChangedListener;
public class Main extends SherlockFragmentActivity implements StateChangedListener {
public class Main extends SherlockFragmentActivity implements StateChangedListener, SyncUpdateFragment.SyncUpdateFragmentInterface {
private ActionBar actionBar;
private FolderFeedListFragment folderFeedList;
private FragmentManager fragmentManager;
private SyncUpdateFragment syncFragment;
private static final String TAG = "MainActivity";
private Menu menu;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupActionBar();
fragmentManager = getSupportFragmentManager();
folderFeedList = (FolderFeedListFragment) fragmentManager.findFragmentByTag("folderFeedListFragment");
}
public void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_PROGRESS);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupActionBar();
fragmentManager = getSupportFragmentManager();
folderFeedList = (FolderFeedListFragment) fragmentManager.findFragmentByTag("folderFeedListFragment");
syncFragment = (SyncUpdateFragment) fragmentManager.findFragmentByTag(SyncUpdateFragment.TAG);
if (syncFragment == null) {
syncFragment = new SyncUpdateFragment();
fragmentManager.beginTransaction().add(syncFragment, SyncUpdateFragment.TAG).commit();
triggerRefresh();
}
}
private void triggerRefresh() {
setSupportProgressBarIndeterminateVisibility(true);
if (menu != null) {
menu.findItem(R.id.menu_refresh).setEnabled(false);
}
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_REFRESH_COUNTS);
startService(intent);
}
private void setupActionBar() {
actionBar = getSupportActionBar();
actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
inflater.inflate(R.menu.main, menu);
this.menu = menu;
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
@ -52,6 +81,9 @@ public class Main extends SherlockFragmentActivity implements StateChangedListen
Intent profileIntent = new Intent(this, Profile.class);
startActivity(profileIntent);
return true;
case R.id.menu_refresh:
triggerRefresh();
return true;
}
return super.onOptionsItemSelected(item);
}
@ -59,8 +91,24 @@ public class Main extends SherlockFragmentActivity implements StateChangedListen
@Override
public void changedState(int state) {
Log.d(TAG, "State changed");
folderFeedList.changeState(state);
}
@Override
public void updateAfterSync() {
Log.d(TAG, "Finished feed count refresh.");
folderFeedList.hasUpdated();
setSupportProgressBarIndeterminateVisibility(false);
menu.findItem(R.id.menu_refresh).setEnabled(true);
}
@Override
public void updateSyncStatus(boolean syncRunning) {
if (syncRunning) {
setSupportProgressBarIndeterminateVisibility(true);
if (menu != null) {
menu.findItem(R.id.menu_refresh).setEnabled(true);
}
}
}
}

View file

@ -1,6 +1,5 @@
package com.newsblur.activity;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
@ -8,8 +7,6 @@ import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.ViewPager;
import android.text.TextUtils;
@ -20,15 +17,11 @@ import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.Window;
import com.newsblur.R;
import com.newsblur.database.FeedProvider;
import com.newsblur.database.ReadingAdapter;
import com.newsblur.domain.Feed;
import com.newsblur.domain.Story;
import com.newsblur.service.DetachableResultReceiver;
import com.newsblur.service.DetachableResultReceiver.Receiver;
import com.newsblur.service.SyncService;
import com.newsblur.util.UIUtils;
public class Reading extends SherlockFragmentActivity {
@ -47,9 +40,6 @@ public class Reading extends SherlockFragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceBundle) {
requestWindowFeature(Window.FEATURE_PROGRESS);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
super.onCreate(savedInstanceBundle);
setContentView(R.layout.activity_reading);
@ -58,12 +48,12 @@ public class Reading extends SherlockFragmentActivity {
passedPosition = getIntent().getIntExtra(EXTRA_POSITION, 0);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
contentResolver = getContentResolver();
contentResolver = getContentResolver();
Uri storiesURI = FeedProvider.STORIES_URI.buildUpon().appendPath(feedId).build();
Cursor stories = contentResolver.query(storiesURI, null, null, null, null);
readingAdapter = new ReadingAdapter(fragmentManager, this, feedId, stories);
final Uri feedUri = FeedProvider.FEEDS_URI.buildUpon().appendPath(feedId).build();
feed = Feed.fromCursor(contentResolver.query(feedUri, null, null, null, null));
setTitle(feed.title);

View file

@ -3,6 +3,7 @@ package com.newsblur.database;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.text.TextUtils;
import android.util.Log;
public class BlurDatabase extends SQLiteOpenHelper {
@ -12,17 +13,17 @@ public class BlurDatabase extends SQLiteOpenHelper {
private final static String TAG = "DatabaseHelper";
private final static String DB_NAME = "blur.db";
private final static int VERSION = 1;
public BlurDatabase(Context context) {
super(context, DB_NAME, null, VERSION);
Log.d(TAG, "Initiating database");
}
private final String FOLDER_SQL = "CREATE TABLE " + DatabaseConstants.FOLDER_TABLE + " (" +
DatabaseConstants.FOLDER_ID + INTEGER + ", " +
DatabaseConstants.FOLDER_NAME + TEXT + " PRIMARY KEY " +
")";
private final String FEED_SQL = "CREATE TABLE " + DatabaseConstants.FEED_TABLE + " (" +
DatabaseConstants.FEED_ID + INTEGER + " PRIMARY KEY, " +
DatabaseConstants.FEED_ACTIVE + TEXT + ", " +
@ -39,7 +40,16 @@ public class BlurDatabase extends SQLiteOpenHelper {
DatabaseConstants.FEED_TITLE + TEXT + ", " +
DatabaseConstants.FEED_UPDATED_SECONDS +
")";
private final String COMMENT_SQL = "CREATE TABLE " + DatabaseConstants.COMMENT_TABLE + " (" +
DatabaseConstants.COMMENT_DATE + TEXT + ", " +
DatabaseConstants.COMMENT_SHAREDDATE + TEXT + ", " +
DatabaseConstants.COMMENT_ID + TEXT + " PRIMARY KEY, " +
DatabaseConstants.COMMENT_STORYID + TEXT + ", " +
DatabaseConstants.COMMENT_TEXT + TEXT + ", " +
DatabaseConstants.COMMENT_USERID + TEXT +
")";
private final String STORY_SQL = "CREATE TABLE " + DatabaseConstants.STORY_TABLE + " (" +
DatabaseConstants.STORY_AUTHORS + TEXT + ", " +
DatabaseConstants.STORY_CONTENT + TEXT + ", " +
@ -52,31 +62,33 @@ public class BlurDatabase extends SQLiteOpenHelper {
DatabaseConstants.STORY_INTELLIGENCE_TITLE + INTEGER + ", " +
DatabaseConstants.STORY_COMMENT_COUNT + INTEGER + ", " +
DatabaseConstants.STORY_SHARE_COUNT + INTEGER + ", " +
DatabaseConstants.STORY_SHARED_USER_IDS + TEXT + ", " +
DatabaseConstants.STORY_TAGS + TEXT + ", " +
DatabaseConstants.STORY_PERMALINK + TEXT + ", " +
DatabaseConstants.STORY_READ + TEXT + ", " +
DatabaseConstants.STORY_TITLE + TEXT +
")";
private final String CLASSIFIER_SQL = "CREATE TABLE " + DatabaseConstants.CLASSIFIER_TABLE + " (" +
DatabaseConstants.CLASSIFIER_ID + TEXT + ", " +
DatabaseConstants.CLASSIFIER_KEY + TEXT + ", " +
DatabaseConstants.CLASSIFIER_TYPE + TEXT + ", " +
DatabaseConstants.CLASSIFIER_VALUE + TEXT +
")";
private final String FEED_FOLDER_SQL = "CREATE TABLE " + DatabaseConstants.FEED_FOLDER_MAP_TABLE + " (" +
DatabaseConstants.FEED_FOLDER_FOLDER_NAME + TEXT + ", " +
DatabaseConstants.FEED_FOLDER_FEED_ID + INTEGER + ", " +
"PRIMARY KEY (" + DatabaseConstants.FEED_FOLDER_FOLDER_NAME + ", " + DatabaseConstants.FEED_FOLDER_FEED_ID + ") " +
")";
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(FEED_SQL);
db.execSQL(FOLDER_SQL);
db.execSQL(STORY_SQL);
db.execSQL(COMMENT_SQL);
db.execSQL(CLASSIFIER_SQL);
db.execSQL(FEED_FOLDER_SQL);
}

View file

@ -33,6 +33,8 @@ public class DatabaseConstants {
public static final String FEED_FOLDER_FEED_ID = "feed_feed_id";
public static final String FEED_FOLDER_FOLDER_NAME = "feed_folder_name";
public static final String COMMENT_TABLE = "comments";
public static final String CLASSIFIER_TABLE = "classifiers";
public static final String CLASSIFIER_ID = BaseColumns._ID;
public static final String CLASSIFIER_TYPE = "type";
@ -55,19 +57,32 @@ public class DatabaseConstants {
public static final String STORY_READ = "read";
public static final String STORY_TAGS = "tags";
public static final String STORY_FEED_ID = "feed_id";
public static final String STORY_SHARED_USER_IDS = "shared_user_ids";
public static final String COMMENT_ID = BaseColumns._ID;
public static final String COMMENT_STORYID = "comment_storyid";
public static final String COMMENT_TEXT = "comment_text";
public static final String COMMENT_DATE = "comment_date";
public static final String COMMENT_SHAREDDATE = "comment_shareddate";
public static final String COMMENT_USERID = "comment_userid";
// Aggregated columns
public static final String SUM_POS = "sum_postive";
public static final String SUM_NEUT = "sum_neutral";
public static final String SUM_NEG = "sum_negative";
public static final String[] COMMENT_COLUMNS = {
COMMENT_ID, COMMENT_STORYID, COMMENT_TEXT, COMMENT_USERID, COMMENT_DATE, COMMENT_SHAREDDATE
};
public static final String[] FOLDER_COLUMNS = {
FOLDER_TABLE + "." + FOLDER_ID, FOLDER_TABLE + "." + FOLDER_NAME, " SUM(" + FEED_POSITIVE_COUNT + ") AS " + SUM_POS, " SUM(" + FEED_NEUTRAL_COUNT + ") AS " + SUM_NEUT, " SUM(" + FEED_NEGATIVE_COUNT + ") AS " + SUM_NEG
};
public static final String[] STORY_COLUMNS = {
STORY_AUTHORS, STORY_COMMENT_COUNT, STORY_CONTENT, STORY_DATE, STORY_FEED_ID, STORY_ID, STORY_INTELLIGENCE_AUTHORS, STORY_INTELLIGENCE_FEED, STORY_INTELLIGENCE_TAGS, STORY_INTELLIGENCE_TITLE,
STORY_PERMALINK, STORY_READ, STORY_SHARE_COUNT, STORY_TAGS, STORY_TITLE
STORY_PERMALINK, STORY_READ, STORY_SHARE_COUNT, STORY_TAGS, STORY_TITLE, STORY_SHARED_USER_IDS
};
}

View file

@ -16,6 +16,7 @@ public class FeedProvider extends ContentProvider {
public static final Uri NEWSBLUR_URI = Uri.parse("content://" + AUTHORITY + "/" + VERSION);
public static final Uri FEEDS_URI = Uri.parse("content://" + AUTHORITY + "/" + VERSION + "/feeds/");
public static final Uri STORIES_URI = Uri.parse("content://" + AUTHORITY + "/" + VERSION + "/stories/");
public static final Uri COMMENTS_URI = Uri.parse("content://" + AUTHORITY + "/" + VERSION + "/comments/");
public static final Uri FEED_FOLDER_MAP_URI = Uri.parse("content://" + AUTHORITY + "/" + VERSION + "/feedfoldermap/");
public static final Uri FOLDERS_URI = Uri.parse("content://" + AUTHORITY + "/" + VERSION + "/folders/");
@ -27,6 +28,7 @@ public class FeedProvider extends ContentProvider {
private static final int ALL_FEEDS = 0;
private static final int FEED_STORIES = 1;
private static final int STORY_COMMENTS = 7;
private static final int ALL_FOLDERS = 2;
private static final int SPECIFIC_FOLDER = 3;
private static final int FEED_FOLDER_MAP = 4;
@ -41,6 +43,7 @@ public class FeedProvider extends ContentProvider {
uriMatcher.addURI(AUTHORITY, VERSION + "/feeds/", ALL_FEEDS);
uriMatcher.addURI(AUTHORITY, VERSION + "/feeds/*/", INDIVIDUAL_FEED);
uriMatcher.addURI(AUTHORITY, VERSION + "/stories/#/", FEED_STORIES);
uriMatcher.addURI(AUTHORITY, VERSION + "/comments/", STORY_COMMENTS);
uriMatcher.addURI(AUTHORITY, VERSION + "/feedfoldermap/", FEED_FOLDER_MAP);
uriMatcher.addURI(AUTHORITY, VERSION + "/feedfoldermap/*/", SPECIFIC_FEED_FOLDER_MAP);
uriMatcher.addURI(AUTHORITY, VERSION + "/folders/", ALL_FOLDERS);
@ -90,6 +93,14 @@ public class FeedProvider extends ContentProvider {
resultUri = uri.buildUpon().appendPath(values.getAsString(DatabaseConstants.FEED_ID)).build();
break;
// Inserting a comment
case STORY_COMMENTS:
db.beginTransaction();
db.insertWithOnConflict(DatabaseConstants.COMMENT_TABLE, null, values, SQLiteDatabase.CONFLICT_REPLACE);
db.setTransactionSuccessful();
db.endTransaction();
break;
// Inserting a story
case FEED_STORIES:
db.beginTransaction();
@ -97,51 +108,51 @@ public class FeedProvider extends ContentProvider {
db.setTransactionSuccessful();
db.endTransaction();
break;
case UriMatcher.NO_MATCH:
Log.d(TAG, "No match found for URI: " + uri.toString());
break;
}
db.close();
return resultUri;
}
@Override
public boolean onCreate() {
Log.d(TAG, "Creating provider and database.");
databaseHelper = new BlurDatabase(getContext().getApplicationContext());
databaseHelper = new BlurDatabase(getContext());
return true;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
final SQLiteDatabase db = databaseHelper.getReadableDatabase();
Cursor cursor = null;
switch (uriMatcher.match(uri)) {
// Query for all feeds (by default only return those that have unread items in them)
case ALL_FEEDS:
cursor = db.rawQuery("SELECT " + TextUtils.join(",", DatabaseConstants.FEED_COLUMNS) + " FROM " + DatabaseConstants.FEED_FOLDER_MAP_TABLE +
return db.rawQuery("SELECT " + TextUtils.join(",", DatabaseConstants.FEED_COLUMNS) + " FROM " + DatabaseConstants.FEED_FOLDER_MAP_TABLE +
" INNER JOIN " + DatabaseConstants.FEED_TABLE +
" ON " + DatabaseConstants.FEED_TABLE + "." + DatabaseConstants.FEED_ID + " = " + DatabaseConstants.FEED_FOLDER_MAP_TABLE + "." + DatabaseConstants.FEED_FOLDER_FEED_ID +
" WHERE (" + DatabaseConstants.FEED_NEGATIVE_COUNT + " + " + DatabaseConstants.FEED_NEUTRAL_COUNT + " + " + DatabaseConstants.FEED_POSITIVE_COUNT + ") > 0 " +
" ORDER BY " + DatabaseConstants.FEED_TABLE + "." + DatabaseConstants.FEED_TITLE + " COLLATE NOCASE", selectionArgs);
break;
// Query for a specific feed
// Query for a specific feed
case INDIVIDUAL_FEED:
cursor = db.rawQuery("SELECT " + TextUtils.join(",", DatabaseConstants.FEED_COLUMNS) + " FROM " + DatabaseConstants.FEED_TABLE +
" WHERE " + DatabaseConstants.FEED_ID + "= '" + uri.getLastPathSegment() + "'", selectionArgs);
break;
// Querying for a stories from a feed
return db.rawQuery("SELECT " + TextUtils.join(",", DatabaseConstants.FEED_COLUMNS) + " FROM " + DatabaseConstants.FEED_TABLE +
" WHERE " + DatabaseConstants.FEED_ID + "= '" + uri.getLastPathSegment() + "'", selectionArgs);
// Querying for a stories from a feed
case FEED_STORIES:
selection = DatabaseConstants.STORY_FEED_ID + " = ?";
selectionArgs = new String[] { uri.getLastPathSegment() };
cursor = db.query(DatabaseConstants.STORY_TABLE, DatabaseConstants.STORY_COLUMNS, selection, selectionArgs, null, null, null);
break;
return db.query(DatabaseConstants.STORY_TABLE, DatabaseConstants.STORY_COLUMNS, selection, selectionArgs, null, null, null);
// Query for feeds with no folder mapping
// Querying for a stories from a feed
case STORY_COMMENTS:
selection = DatabaseConstants.COMMENT_STORYID + " = ?";
return db.query(DatabaseConstants.COMMENT_TABLE, DatabaseConstants.COMMENT_COLUMNS, selection, selectionArgs, null, null, null);
// Query for feeds with no folder mapping
case FEED_FOLDER_MAP:
String nullFolderQuery = "SELECT " + TextUtils.join(",", DatabaseConstants.FEED_COLUMNS) + " FROM " + DatabaseConstants.FEED_TABLE +
" LEFT JOIN " + DatabaseConstants.FEED_FOLDER_MAP_TABLE +
@ -155,10 +166,9 @@ public class FeedProvider extends ContentProvider {
nullFolderBuilder.append(selectionArgs[0]);
}
nullFolderBuilder.append(" ORDER BY " + DatabaseConstants.FEED_TABLE + "." + DatabaseConstants.FEED_TITLE + " COLLATE NOCASE");
cursor = db.rawQuery(nullFolderBuilder.toString(), null);
break;
return db.rawQuery(nullFolderBuilder.toString(), null);
// Querying for feeds for a given folder
// Querying for feeds for a given folder
case SPECIFIC_FEED_FOLDER_MAP:
selection = DatabaseConstants.FOLDER_ID + " = ?";
String[] folderArguments = new String[] { uri.getLastPathSegment() };
@ -175,10 +185,9 @@ public class FeedProvider extends ContentProvider {
builder.append(selectionArgs[0]);
}
builder.append(" ORDER BY " + DatabaseConstants.FEED_TABLE + "." + DatabaseConstants.FEED_TITLE + " COLLATE NOCASE");
cursor = db.rawQuery(builder.toString(), folderArguments);
break;
return db.rawQuery(builder.toString(), folderArguments);
// Querying for all folders with unread items
// Querying for all folders with unread items
case ALL_FOLDERS:
String folderQuery = "SELECT " + TextUtils.join(",", DatabaseConstants.FOLDER_COLUMNS) + " FROM " + DatabaseConstants.FEED_FOLDER_MAP_TABLE +
" LEFT JOIN " + DatabaseConstants.FOLDER_TABLE +
@ -194,15 +203,24 @@ public class FeedProvider extends ContentProvider {
}
folderBuilder.append(" ORDER BY ");
folderBuilder.append(DatabaseConstants.FOLDER_TABLE + "." + DatabaseConstants.FOLDER_NAME + " COLLATE NOCASE");
cursor = db.rawQuery(folderBuilder.toString(), null);
break;
return db.rawQuery(folderBuilder.toString(), null);
default:
throw new UnsupportedOperationException("Unknown URI: " + uri);
}
return cursor;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
final SQLiteDatabase db = databaseHelper.getWritableDatabase();
switch (uriMatcher.match(uri)) {
case INDIVIDUAL_FEED:
return db.update(DatabaseConstants.FEED_TABLE, values, DatabaseConstants.FEED_ID + " = ?", new String[] { uri.getLastPathSegment() });
default:
throw new UnsupportedOperationException("Unknown URI: " + uri);
}
}

View file

@ -86,6 +86,7 @@ public class Feed {
feed.positiveCount = childCursor.getInt(childCursor.getColumnIndex(DatabaseConstants.FEED_POSITIVE_COUNT));
feed.subscribers = childCursor.getString(childCursor.getColumnIndex(DatabaseConstants.FEED_SUBSCRIBERS));
feed.title = childCursor.getString(childCursor.getColumnIndex(DatabaseConstants.FEED_TITLE));
childCursor.close();
return feed;
}

View file

@ -4,8 +4,6 @@ import java.io.Serializable;
import android.content.ContentValues;
import android.database.Cursor;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import com.google.gson.annotations.SerializedName;
@ -22,6 +20,9 @@ public class Story implements Serializable {
@SerializedName("share_count")
public String shareCount;
@SerializedName("share_user_ids")
public String[] sharedUserIds;
@SerializedName("comment_count")
public String commentCount;
@ -38,7 +39,7 @@ public class Story implements Serializable {
@SerializedName("story_title")
public String title;
@SerializedName("short_parsed_date")
@SerializedName("story_date")
public String date;
@SerializedName("story_content")
@ -50,12 +51,12 @@ public class Story implements Serializable {
@SerializedName("story_feed_id")
public String feedId;
@SerializedName("public_comments")
public Comment[] comments;
@SerializedName("intelligence")
public Intelligence intelligence = new Intelligence();
@SerializedName("intelligence_title")
public String intelligenceTitle;
public ContentValues getValues() {
final ContentValues values = new ContentValues();
values.put(DatabaseConstants.STORY_ID, id);
@ -66,6 +67,7 @@ public class Story implements Serializable {
values.put(DatabaseConstants.STORY_COMMENT_COUNT, commentCount);
values.put(DatabaseConstants.STORY_SHARE_COUNT, shareCount);
values.put(DatabaseConstants.STORY_AUTHORS, authors);
values.put(DatabaseConstants.STORY_SHARED_USER_IDS, TextUtils.join(",", sharedUserIds));
values.put(DatabaseConstants.STORY_INTELLIGENCE_AUTHORS, intelligence.intelligenceAuthors);
values.put(DatabaseConstants.STORY_INTELLIGENCE_FEED, intelligence.intelligenceFeed);
values.put(DatabaseConstants.STORY_INTELLIGENCE_TAGS, intelligence.intelligenceTags);
@ -85,6 +87,7 @@ public class Story implements Serializable {
story.shareCount = cursor.getString(cursor.getColumnIndex(DatabaseConstants.STORY_SHARE_COUNT));
story.commentCount = cursor.getString(cursor.getColumnIndex(DatabaseConstants.STORY_COMMENT_COUNT));
story.permalink = cursor.getString(cursor.getColumnIndex(DatabaseConstants.STORY_PERMALINK));
story.sharedUserIds = TextUtils.split(cursor.getString(cursor.getColumnIndex(DatabaseConstants.STORY_SHARED_USER_IDS)), ",");
story.intelligence.intelligenceAuthors = cursor.getInt(cursor.getColumnIndex(DatabaseConstants.STORY_INTELLIGENCE_AUTHORS));
story.intelligence.intelligenceFeed = cursor.getInt(cursor.getColumnIndex(DatabaseConstants.STORY_INTELLIGENCE_FEED));
story.intelligence.intelligenceTags = cursor.getInt(cursor.getColumnIndex(DatabaseConstants.STORY_INTELLIGENCE_TAGS));
@ -96,7 +99,9 @@ public class Story implements Serializable {
return story;
}
private class Intelligence {
private class Intelligence implements Serializable {
private static final long serialVersionUID = -1314486209455376730L;
@SerializedName("feed")
public int intelligenceFeed = 0;
@ -109,5 +114,6 @@ public class Story implements Serializable {
@SerializedName("title")
public int intelligenceTitle = 0;
}
}

View file

@ -15,11 +15,9 @@ import android.widget.ExpandableListView.OnGroupClickListener;
import com.newsblur.R;
import com.newsblur.activity.ItemsList;
import com.newsblur.activity.Reading;
import com.newsblur.database.DatabaseConstants;
import com.newsblur.database.FeedProvider;
import com.newsblur.database.FolderTreeAdapter;
import com.newsblur.domain.Feed;
import com.newsblur.util.AppConstants;
import com.newsblur.util.UIUtils;
import com.newsblur.view.FolderTreeViewBinder;
@ -50,6 +48,11 @@ public class FolderFeedListFragment extends Fragment implements OnGroupClickList
folderAdapter = new FolderTreeAdapter(getActivity(), cursor, R.layout.row_folder_collapsed, groupFrom, groupTo, R.layout.row_feed, childFrom, childTo);
folderAdapter.setViewBinder(viewBinder);
}
public void hasUpdated() {
folderAdapter.getCursor().requery();
folderAdapter.notifyDataSetChanged();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@ -68,7 +71,6 @@ public class FolderFeedListFragment extends Fragment implements OnGroupClickList
}
public void changeState(int state) {
String selection = null;
viewBinder.setState(state);

View file

@ -82,8 +82,9 @@ public class ItemListFragment extends Fragment implements LoaderManager.LoaderCa
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
Log.d(TAG, "Load finished: " + cursor.getCount());
adapter.swapCursor(cursor);
if (cursor != null) {
adapter.swapCursor(cursor);
}
}
public void updated() {

View file

@ -100,7 +100,7 @@ public class ProfileDetailsFragment extends Fragment implements OnClickListener
followingCount.setText("" + user.followingCount);
if (!viewingSelf) {
imageLoader.DisplayImage(user.photoUrl, imageView);
imageLoader.displayImage(user.photoUrl, user.userId, imageView);
if (user.followedByYou) {
unfollowButton.setVisibility(View.VISIBLE);
followButton.setVisibility(View.GONE);

View file

@ -1,58 +1,146 @@
package com.newsblur.fragment;
import java.util.ArrayList;
import java.util.List;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.GridLayout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.newsblur.R;
import com.newsblur.activity.Profile;
import com.newsblur.database.FeedProvider;
import com.newsblur.domain.Comment;
import com.newsblur.domain.Story;
import com.newsblur.domain.UserProfile;
import com.newsblur.network.APIManager;
import com.newsblur.network.domain.ProfileResponse;
import com.newsblur.util.ImageLoader;
import com.newsblur.util.UIUtils;
public class ReadingItemFragment extends Fragment {
Story story;
LayoutInflater inflater;
private static final String TAG = "ReadingItemFragment";
private Story story;
private LayoutInflater inflater;
private APIManager apiManager;
private ImageLoader imageLoader = new ImageLoader(getActivity());
public static ReadingItemFragment newInstance(Story story) {
ReadingItemFragment readingFragment = new ReadingItemFragment();
// Supply num input as an argument.
Bundle args = new Bundle();
args.putSerializable("story", story);
readingFragment.setArguments(args);
return readingFragment;
Bundle args = new Bundle();
args.putSerializable("story", story);
readingFragment.setArguments(args);
return readingFragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
apiManager = new APIManager(getActivity());
story = getArguments() != null ? (Story) getArguments().getSerializable("story") : null;
}
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
this.inflater = inflater;
View view = inflater.inflate(R.layout.fragment_readingitem, null);
WebView web = (WebView) view.findViewById(R.id.reading_webview);
setupWebview(web);
setupItemMetadata(view);
if (story.sharedUserIds.length > 0) {
view.findViewById(R.id.reading_shared_container).setVisibility(View.VISIBLE);
setupItemCommentsAndShares(view);
}
return view;
}
private void setupItemCommentsAndShares(final View view) {
new AsyncTask<Void, Void, Void>() {
private List<UserProfile> profiles = new ArrayList<UserProfile>();
private ArrayList<View> commentViews;
@Override
protected Void doInBackground(Void... arg0) {
inflater = getActivity().getLayoutInflater();
for (String userId : story.sharedUserIds) {
if (!imageLoader.checkForImage(userId)) {
ProfileResponse user = apiManager.getUser(userId);
imageLoader.cacheImage(user.user.photoUrl, user.user.userId);
}
}
ContentResolver resolver = getActivity().getContentResolver();
Cursor cursor = resolver.query(FeedProvider.COMMENTS_URI, null, null, new String[] { story.id }, null);
commentViews = new ArrayList<View>();
while (cursor.moveToNext()) {
Comment comment = Comment.fromCursor(cursor);
View commentView = inflater.inflate(R.layout.include_comment, null);
TextView commentText = (TextView) commentView.findViewById(R.id.comment_text);
commentText.setText(comment.commentText);
ImageView commentImage = (ImageView) commentView.findViewById(R.id.comment_user_image);
imageLoader.displayImage(Integer.toString(comment.userId), commentImage);
TextView commentSharedDate = (TextView) commentView.findViewById(R.id.comment_shareddate);
commentSharedDate.setText(comment.sharedDate);
commentViews.add(commentView);
}
return null;
}
protected void onPostExecute(Void result) {
for (final String userId : story.sharedUserIds) {
ImageView image = new ImageView(getActivity());
image.setMaxHeight(UIUtils.convertDPsToPixels(getActivity(), 20));
image.setMaxWidth(UIUtils.convertDPsToPixels(getActivity(), 20));
GridLayout grid = (GridLayout) view.findViewById(R.id.reading_social_shareimages);
grid.addView(image);
imageLoader.displayImage(userId, image);
image.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
Intent i = new Intent(getActivity(), Profile.class);
i.putExtra(Profile.USER_ID, userId);
startActivity(i);
}
});
}
for (View comment : commentViews) {
((LinearLayout) view.findViewById(R.id.reading_comment_container)).addView(comment);
}
};
}.execute();
}
private void setupItemMetadata(View view) {
TextView itemTitle = (TextView) view.findViewById(R.id.reading_item_title);
TextView itemDate = (TextView) view.findViewById(R.id.reading_item_date);
TextView itemAuthors = (TextView) view.findViewById(R.id.reading_item_authors);
GridLayout tagContainer = (GridLayout) view.findViewById(R.id.reading_item_tags);
if (story.tags != null || story.tags.length > 0) {
tagContainer.setVisibility(View.VISIBLE);
for (String tag : story.tags) {
@ -62,7 +150,7 @@ public class ReadingItemFragment extends Fragment {
tagContainer.addView(v);
}
}
itemDate.setText(story.date);
itemTitle.setText(story.title);
itemAuthors.setText(story.authors);
@ -79,7 +167,7 @@ public class ReadingItemFragment extends Fragment {
web.getSettings().setAppCacheEnabled(true);
web.setVerticalScrollBarEnabled(false);
web.setHorizontalScrollBarEnabled(false);
StringBuilder builder = new StringBuilder();
// TODO: Define a better strategy for rescaling the HTML across device screen sizes and storying this HTML as boilderplate somewhere
builder.append("<html><head><meta name=\"viewport\" content=\"target-densitydpi=device-dpi\" /><link rel=\"stylesheet\" type=\"text/css\" href=\"reading.css\" /></head><body>");
@ -88,5 +176,5 @@ public class ReadingItemFragment extends Fragment {
web.loadDataWithBaseURL("file:///android_asset/", builder.toString(), "text/html", "UTF-8", null);
}
}

View file

@ -57,7 +57,7 @@ public class APIClient {
final StringBuilder builder = new StringBuilder();
builder.append((String) entry.getKey());
builder.append("=");
builder.append((String) entry.getValue());
builder.append(URLEncoder.encode((String) entry.getValue()));
parameters.add(builder.toString());
}
final String parameterString = TextUtils.join("&", parameters);

View file

@ -10,14 +10,20 @@ public class APIConstants {
public static final String URL_UNFOLLOW = "http://dev.newsblur.com/social/unfollow";
public static final String URL_USER_INTERACTIONS = "http://dev.newsblur.com/social/interactions";
public static final String URL_FEEDS_STORIES = "http://dev.newsblur.com/reader/river_stories";
public static final String URL_RIVER_STORIES = "http://dev.newsblur.com/reader/river_stories";
public static final String URL_FEED_STORIES = "http://dev.newsblur.com/reader/feed";
public static final String URL_SIGNUP = "http://dev.newsblur.com/api/signup";
public static final String URL_FEED_COUNTS = "http://dev.newsblur.com/reader/refresh_feeds/";
public static final String PARAMETER_FEEDS = "feeds";
public static final String PARAMETER_PASSWORD = "password";
public static final String PARAMETER_USER_ID = "user_id";
public static final String PARAMETER_USERNAME = "username";
public static final String PARAMETER_USERID = "user_id";
public static final String PARAMETER_STORYID = "story_id";
public static final String PARAMETER_FEEDID = "feed_id";
public static final String NEWSBLUR_URL = "http://www.newsblur.com";
}

View file

@ -9,15 +9,18 @@ import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.newsblur.database.DatabaseConstants;
import com.newsblur.database.FeedProvider;
import com.newsblur.domain.Comment;
import com.newsblur.domain.Feed;
import com.newsblur.domain.FolderStructure;
import com.newsblur.domain.Story;
import com.newsblur.network.domain.FeedFolderResponse;
import com.newsblur.network.domain.FeedRefreshResponse;
import com.newsblur.network.domain.LoginResponse;
import com.newsblur.network.domain.ProfileResponse;
import com.newsblur.network.domain.StoriesResponse;
@ -85,13 +88,23 @@ public class APIManager {
final APIClient client = new APIClient(context);
final ContentValues values = new ContentValues();
values.put(APIConstants.PARAMETER_FEEDS, feedId);
client.get(APIConstants.URL_FEEDS_STORIES, values);
final APIResponse response = client.get(APIConstants.URL_FEEDS_STORIES, values);
Uri feedUri = Uri.parse(APIConstants.URL_FEED_STORIES).buildUpon().appendPath(feedId).build();
final APIResponse response = client.get(feedUri.toString(), values);
StoriesResponse storiesResponse = gson.fromJson(response.responseString, StoriesResponse.class);
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
Uri feedUri = FeedProvider.STORIES_URI.buildUpon().appendPath(feedId).build();
Uri storyUri = FeedProvider.STORIES_URI.buildUpon().appendPath(feedId).build();
for (Story story : storiesResponse.stories) {
contentResolver.insert(feedUri, story.getValues());
contentResolver.insert(storyUri, story.getValues());
for (Comment comment : story.comments) {
StringBuilder builder = new StringBuilder();
builder.append(story.id);
builder.append(story.feedId);
builder.append(comment.userId);
comment.storyId = story.id;
comment.id = (builder.toString());
contentResolver.insert(FeedProvider.COMMENTS_URI, comment.getValues());
}
}
return storiesResponse;
} else {
@ -160,4 +173,16 @@ public class APIManager {
}
}
public void refreshFeedCounts() {
final APIClient client = new APIClient(context);
final APIResponse response = client.get(APIConstants.URL_FEED_COUNTS);
if (response.responseCode == HttpStatus.SC_OK && !response.hasRedirected) {
final FeedRefreshResponse feedCountUpdate = gson.fromJson(response.responseString, FeedRefreshResponse.class);
for (String feedId : feedCountUpdate.feedCounts.keySet()) {
Uri feedUri = FeedProvider.FEEDS_URI.buildUpon().appendPath(feedId).build();
contentResolver.update(feedUri, feedCountUpdate.feedCounts.get(feedId).getValues(), null, null);
}
}
}
}

View file

@ -9,7 +9,6 @@ import android.util.Log;
import com.newsblur.network.APIClient;
import com.newsblur.network.APIManager;
import com.newsblur.network.domain.StoriesResponse;
/**
* The SyncService is based on an app architecture that tries to place network calls
@ -25,13 +24,14 @@ public class SyncService extends IntentService {
public static final String EXTRA_STATUS_RECEIVER = "resultReceiverExtra";
public static final String EXTRA_TASK_FEED_ID = "taskFeedId";
public final static int STATUS_RUNNING = 0;
public final static int STATUS_FINISHED = 1;
public final static int STATUS_ERROR = 2;
public static final int NOT_RUNNING = -1;
public final static int STATUS_RUNNING = 0x02;
public final static int STATUS_FINISHED = 0x03;
public final static int STATUS_ERROR = 0x04;
public static final int NOT_RUNNING = 0x01;
public static final int EXTRA_TASK_FOLDER_UPDATE = 30;
public static final int EXTRA_TASK_FEED_UPDATE = 31;
public static final int EXTRA_TASK_REFRESH_COUNTS = 32;
public APIClient apiClient;
private APIManager apiManager;
@ -60,6 +60,9 @@ public class SyncService extends IntentService {
case EXTRA_TASK_FOLDER_UPDATE:
apiManager.getFolderFeedMapping();
break;
case EXTRA_TASK_REFRESH_COUNTS:
apiManager.refreshFeedCounts();
break;
case EXTRA_TASK_FEED_UPDATE:
if (!TextUtils.isEmpty(intent.getStringExtra(EXTRA_TASK_FEED_ID))) {
apiManager.getStoriesForFeed(intent.getStringExtra(EXTRA_TASK_FEED_ID));

View file

@ -34,26 +34,43 @@ public class ImageLoader {
fileCache = new FileCache(context);
executorService = Executors.newFixedThreadPool(5);
}
public void DisplayImage(String url, ImageView imageView) {
imageViews.put(imageView, url);
Bitmap bitmap = memoryCache.get(url);
public void displayImage(String url, String uid, ImageView imageView) {
imageViews.put(imageView, uid);
Bitmap bitmap = memoryCache.get(uid);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
} else {
queuePhoto(url, imageView);
queuePhoto(url, uid, imageView);
imageView.setImageResource(R.drawable.logo);
}
}
private void queuePhoto(String url, ImageView imageView) {
PhotoToLoad p = new PhotoToLoad(url, imageView);
executorService.submit(new PhotosLoader(p));
// Display an image assuming it's in cache
public void displayImage(String uid, ImageView imageView) {
Bitmap bitmap = memoryCache.get(uid);
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
} else {
File f= fileCache.getFile(uid);
bitmap = BitmapFactory.decodeFile(f.getAbsolutePath());
memoryCache.put(uid, bitmap);
imageView.setImageBitmap(bitmap);
}
}
private Bitmap getBitmap(String url) {
private void queuePhoto(String url, String uid, ImageView imageView) {
PhotoToLoad p = new PhotoToLoad(url, uid, imageView);
executorService.submit(new PhotosLoader(p));
}
public boolean checkForImage(String uid) {
return (fileCache.getFile(uid) != null || memoryCache.get(uid) != null);
}
private Bitmap getBitmap(String url, String uid) {
File f = fileCache.getFile(url);
File f = fileCache.getFile(uid);
Bitmap bitmap = BitmapFactory.decodeFile(f.getAbsolutePath());
if (bitmap != null) {
@ -88,8 +105,10 @@ public class ImageLoader {
private class PhotoToLoad {
public String url;
public ImageView imageView;
public PhotoToLoad(final String u, final ImageView i) {
public String uid;
public PhotoToLoad(final String u, final String id, final ImageView i) {
url = u;
uid = id;
imageView = i;
}
}
@ -107,8 +126,8 @@ public class ImageLoader {
return;
}
Bitmap bmp = getBitmap(photoToLoad.url);
memoryCache.put(photoToLoad.url, bmp);
Bitmap bmp = getBitmap(photoToLoad.url, photoToLoad.uid);
memoryCache.put(photoToLoad.uid, bmp);
if (imageViewReused(photoToLoad)) {
return;
}
@ -121,7 +140,7 @@ public class ImageLoader {
private boolean imageViewReused(PhotoToLoad photoToLoad){
final String tag = imageViews.get(photoToLoad.imageView);
return (tag == null || !tag.equals(photoToLoad.url));
return (tag == null || !tag.equals(photoToLoad.uid));
}
private class BitmapDisplayer implements Runnable {
@ -148,4 +167,8 @@ public class ImageLoader {
fileCache.clear();
}
public void cacheImage(String photoUrl, String userId) {
getBitmap(photoUrl, userId);
}
}

View file

@ -113,7 +113,7 @@ public class ActivitiesAdapter extends ArrayAdapter<ActivitiesResponse> {
ImageView imageView = (ImageView) view.findViewById(R.id.row_activity_icon);
activityTime.setText(activity.timeSince + " " + ago);
imageLoader.DisplayImage(activity.user.photoUrl, imageView);
imageLoader.displayImage(activity.user.photoUrl, activity.id, imageView);
activityText.setText(stringBuilder);
activityText.setMovementMethod(LinkMovementMethod.getInstance());