aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorSize432015-06-10 13:32:51 +0200
committerSize432015-06-10 13:32:51 +0200
commitd060db73cc45b9248305dff7277500502034e7a9 (patch)
treee312740a7b94a151e7fc1c809f016724e69ba578 /app
parentFeed titles from RSS feeds (diff)
parentMerge branch 'master' of github:camilstaps/RSSin (diff)
Merge branch 'master' of http://github.com/camilstaps/RSSin
Diffstat (limited to 'app')
-rwxr-xr-xapp/src/main/java/org/rssin/android/FeedSorterProvider.java13
-rwxr-xr-xapp/src/main/java/org/rssin/android/FeedSorterTrainer.java1
-rw-r--r--app/src/main/java/org/rssin/android/FeedsList.java26
-rwxr-xr-xapp/src/main/java/org/rssin/android/FiltersList.java2
-rw-r--r--app/src/main/java/org/rssin/android/InternalStorageProvider.java33
-rwxr-xr-xapp/src/main/java/org/rssin/android/NavigationDrawerAllFeedsFragment.java25
-rwxr-xr-xapp/src/main/java/org/rssin/android/NavigationDrawerFeedFragment.java21
-rwxr-xr-xapp/src/main/java/org/rssin/android/NavigationDrawerFilterFragment.java22
-rwxr-xr-xapp/src/main/java/org/rssin/android/SharedPreferencesStorageProvider.java13
-rw-r--r--app/src/main/java/org/rssin/android/VolleyFetcher.java14
-rw-r--r--app/src/main/java/org/rssin/listener/RealtimeListener.java2
-rwxr-xr-xapp/src/main/java/org/rssin/neurons/FeedSorter.java42
-rwxr-xr-xapp/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java8
-rwxr-xr-xapp/src/main/java/org/rssin/neurons/NeuralNetwork.java10
-rwxr-xr-xapp/src/main/java/org/rssin/neurons/Neuron.java9
-rwxr-xr-xapp/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java61
-rwxr-xr-xapp/src/main/java/org/rssin/rssin/SortedFeedItemContainer.java15
-rw-r--r--app/src/main/res/values/feeds.xml66
18 files changed, 171 insertions, 212 deletions
diff --git a/app/src/main/java/org/rssin/android/FeedSorterProvider.java b/app/src/main/java/org/rssin/android/FeedSorterProvider.java
index 0f0748d..fcdeca2 100755
--- a/app/src/main/java/org/rssin/android/FeedSorterProvider.java
+++ b/app/src/main/java/org/rssin/android/FeedSorterProvider.java
@@ -15,11 +15,11 @@ public class FeedSorterProvider {
private static FeedSorterProvider instance;
private FeedSorter sorter = null;
private final String storageKey = "FeedSorter";
- private InternalStorageProvider storageProvider;
+ private final StorageProvider storageProvider;
private FeedSorterProvider(Context context)
{
- storageProvider = InternalStorageProvider.getInstance(context);
+ storageProvider = SharedPreferencesStorageProvider.getInstance(context);
}
public synchronized static FeedSorterProvider getInstance()
@@ -43,8 +43,9 @@ public class FeedSorterProvider {
{
try {
sorter = (FeedSorter) storageProvider.fetch(storageKey, FeedSorter.class);
- } catch (IOException e) {
+ } catch (Exception e) {
sorter = new FeedSorter();
+ Log.v("FST", "Saving new empty sorterProvider", e);
this.save();
}
}
@@ -52,7 +53,7 @@ public class FeedSorterProvider {
return sorter;
}
- public synchronized void save()
+ public void save()
{
FeedSorterStorer storer = new FeedSorterStorer(storageKey, storageProvider, sorter);
new Thread(storer).start();
@@ -72,7 +73,9 @@ public class FeedSorterProvider {
@Override
public void run() {
try {
- storageProvider.store(storageKey, feedSorter);
+ synchronized (feedSorter) {
+ storageProvider.store(storageKey, feedSorter);
+ }
} catch (Exception e) {
Log.e("Filter", "Failed to store FeedSorter", e);
}
diff --git a/app/src/main/java/org/rssin/android/FeedSorterTrainer.java b/app/src/main/java/org/rssin/android/FeedSorterTrainer.java
index 987ed45..54736a0 100755
--- a/app/src/main/java/org/rssin/android/FeedSorterTrainer.java
+++ b/app/src/main/java/org/rssin/android/FeedSorterTrainer.java
@@ -24,7 +24,6 @@ public class FeedSorterTrainer implements Runnable {
}
}
- Log.d("FeedSorterTrainer", "Training stopping...");
sorterProvider.save();
}
}
diff --git a/app/src/main/java/org/rssin/android/FeedsList.java b/app/src/main/java/org/rssin/android/FeedsList.java
index 72a56d1..1036ad3 100644
--- a/app/src/main/java/org/rssin/android/FeedsList.java
+++ b/app/src/main/java/org/rssin/android/FeedsList.java
@@ -1,8 +1,11 @@
package org.rssin.android;
import android.content.Context;
+import android.preference.PreferenceManager;
+import android.util.Log;
import org.rssin.rssin.Feed;
+import org.rssin.rssin.R;
import java.io.IOException;
import java.util.Collections;
@@ -16,18 +19,39 @@ class FeedsList {
private static FeedsList instance;
- private final List<Feed> feeds;
+ private List<Feed> feeds;
private final DefaultStorageProvider storageProvider;
+ public static final boolean USE_DEFAULT_LIST = true;
+
/**
* Fetch from storage provider
* @param context needed to get the storageprovider
* @throws IOException if data is corrupted, and deserializing fails
*/
+ @SuppressWarnings("all")
protected FeedsList(Context context) throws IOException {
storageProvider = DefaultStorageProvider.getInstance(context);
feeds = storageProvider.allFeeds();
sort();
+
+ if (USE_DEFAULT_LIST &&
+ feeds.isEmpty() &&
+ !PreferenceManager.getDefaultSharedPreferences(context).getBoolean("firstload", false)) {
+ String[] feedsList = context.getResources().getStringArray(R.array.default_feeds);
+ for (String url : feedsList) {
+ try {
+ Feed f = new Feed(url);
+ f.store(storageProvider);
+ } catch (Exception e) {
+ Log.w("SPSP", "Couldn't add " + url, e);
+ }
+ }
+ PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean("firstload", true).apply();
+
+ feeds = storageProvider.allFeeds();
+ sort();
+ }
}
public static FeedsList getInstance(Context context) throws IOException {
diff --git a/app/src/main/java/org/rssin/android/FiltersList.java b/app/src/main/java/org/rssin/android/FiltersList.java
index 6b53186..b555e5e 100755
--- a/app/src/main/java/org/rssin/android/FiltersList.java
+++ b/app/src/main/java/org/rssin/android/FiltersList.java
@@ -12,7 +12,7 @@ import java.util.List;
* A list of filters that can be saved using the DefaultStorageProvider
* @author Camil Staps
*/
-public class FiltersList {
+class FiltersList {
private static FiltersList instance;
diff --git a/app/src/main/java/org/rssin/android/InternalStorageProvider.java b/app/src/main/java/org/rssin/android/InternalStorageProvider.java
index c5a7bc1..b6787b4 100644
--- a/app/src/main/java/org/rssin/android/InternalStorageProvider.java
+++ b/app/src/main/java/org/rssin/android/InternalStorageProvider.java
@@ -1,6 +1,7 @@
package org.rssin.android;
import android.content.Context;
+import android.util.Log;
import org.rssin.neurons.FeedSorter;
import org.rssin.rssin.Filter;
@@ -8,6 +9,7 @@ import org.rssin.storage.FilterStorageProvider;
import org.rssin.storage.Storable;
import org.rssin.storage.StorageProvider;
+import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -21,14 +23,15 @@ import java.util.List;
* A way to store data in internal storage
* @author Camil Staps
*/
-class InternalStorageProvider implements StorageProvider<String, Storable>, FilterStorageProvider<String> {
+class InternalStorageProvider implements StorageProvider<String, FeedSorter>, FilterStorageProvider<String> {
protected static final String PREFIX = "storage_", PREFIX_FILTER = "f_", PREFIX_FEEDSORTER = "fs_";
private static InternalStorageProvider instance;
private final Context context;
- private InternalStorageProvider(Context context) {
+ // @todo redo singleton
+ public InternalStorageProvider(Context context) {
this.context = context;
}
@@ -43,7 +46,7 @@ class InternalStorageProvider implements StorageProvider<String, Storable>, Filt
}
@Override
- public synchronized void store(String key, Storable element) throws FileNotFoundException, IOException {
+ public synchronized void store(String key, FeedSorter element) throws FileNotFoundException, IOException {
FileOutputStream fos = context.openFileOutput(getFilename(key, element), Context.MODE_PRIVATE);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(element);
@@ -52,7 +55,7 @@ class InternalStorageProvider implements StorageProvider<String, Storable>, Filt
}
@Override
- public Storable fetch(String key, Class className) throws ClassCastException, FileNotFoundException, IOException {
+ public FeedSorter fetch(String key, Class className) throws ClassCastException, FileNotFoundException, IOException {
return fetchFromFilename(getFilename(key, className));
}
@@ -61,11 +64,11 @@ class InternalStorageProvider implements StorageProvider<String, Storable>, Filt
throw new UnsupportedOperationException("Not implemented yet.");
}
- public Storable fetchFromFilename(String fileName) throws ClassCastException, FileNotFoundException, IOException {
+ public FeedSorter fetchFromFilename(String fileName) throws ClassCastException, FileNotFoundException, IOException {
FileInputStream fis = context.openFileInput(fileName);
ObjectInputStream ois = new ObjectInputStream(fis);
try {
- return (Storable) ois.readObject();
+ return (FeedSorter) ois.readObject();
} catch (ClassNotFoundException e) {
return null;
}
@@ -114,11 +117,11 @@ class InternalStorageProvider implements StorageProvider<String, Storable>, Filt
@Override
public List<Filter> allFilters() {
List<Filter> filters = new ArrayList<>();
- for (String fileName : context.fileList()) {
- try {
- filters.add((Filter) fetchFromFilename(fileName));
- } catch (ClassCastException | IOException e) {}
- }
+// for (String fileName : context.fileList()) {
+// try {
+// filters.add((Filter) fetchFromFilename(fileName));
+// } catch (ClassCastException | IOException e) {}
+// }
return filters;
}
@@ -129,11 +132,11 @@ class InternalStorageProvider implements StorageProvider<String, Storable>, Filt
@Override
public Filter getFilter(String key) {
- try {
- return (Filter) fetch(key, Filter.class);
- } catch (ClassCastException | IOException e) {
+// try {
+// return (Filter) fetch(key, Filter.class);
+// } catch (ClassCastException | IOException e) {
return null;
- }
+// }
}
@Override
diff --git a/app/src/main/java/org/rssin/android/NavigationDrawerAllFeedsFragment.java b/app/src/main/java/org/rssin/android/NavigationDrawerAllFeedsFragment.java
index b7a0d73..e32b7e6 100755
--- a/app/src/main/java/org/rssin/android/NavigationDrawerAllFeedsFragment.java
+++ b/app/src/main/java/org/rssin/android/NavigationDrawerAllFeedsFragment.java
@@ -10,13 +10,12 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import com.android.volley.VolleyError;
-
-import org.rssin.listener.FallibleListener;
+import org.rssin.listener.RealtimeListener;
import org.rssin.rssin.FeedLoaderAndSorter;
import org.rssin.rssin.R;
import org.rssin.rssin.SortedFeedItemContainer;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -42,24 +41,30 @@ public class NavigationDrawerAllFeedsFragment extends Fragment {
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(context);
mRecyclerView.setLayoutManager(mLayoutManager);
+ final FeedItemAdapter feedItemAdapter = new FeedItemAdapter(new ArrayList<SortedFeedItemContainer>());
+ mRecyclerView.setAdapter(feedItemAdapter);
+ mRecyclerView.setHasFixedSize(true);
+
/**
- * @todo Load feeds in separate thread so that the UI is immediately available
- *
* @todo Now, feed items are only returned after *all* feeds have been loaded. With many
* filters that may take a while, so it would be preferable to return intermediate
* results. We could do this for example with {@link org.rssin.listener.RealtimeListener}
*/
FeedLoaderAndSorter loaderAndSorter = new FeedLoaderAndSorter(FeedsList.getInstance().getFeeds());
- loaderAndSorter.getFilteredFeedItems(context, new VolleyFetcher(context), new FallibleListener<List<SortedFeedItemContainer>, VolleyError>() {
+ loaderAndSorter.getFilteredFeedItems(context, VolleyFetcher.getInstance(context), new RealtimeListener<List<SortedFeedItemContainer>, Object>() {
+ @Override
+ public void finish() {
+ // @todo finish
+ }
+
@Override
public void onReceive(List<SortedFeedItemContainer> data) {
- FeedItemAdapter feedItemAdapter = new FeedItemAdapter(data);
- mRecyclerView.setAdapter(feedItemAdapter);
- mRecyclerView.setHasFixedSize(true);
+ feedItemAdapter.feedItems = data;
+ feedItemAdapter.notifyDataSetChanged();
}
@Override
- public void onError(VolleyError error) {
+ public void onError(Object error) {
Frontend.error(context, R.string.error_net_load);
}
});
diff --git a/app/src/main/java/org/rssin/android/NavigationDrawerFeedFragment.java b/app/src/main/java/org/rssin/android/NavigationDrawerFeedFragment.java
index 0f33aca..66b808b 100755
--- a/app/src/main/java/org/rssin/android/NavigationDrawerFeedFragment.java
+++ b/app/src/main/java/org/rssin/android/NavigationDrawerFeedFragment.java
@@ -13,6 +13,7 @@ import android.view.ViewGroup;
import com.android.volley.VolleyError;
import org.rssin.listener.FallibleListener;
+import org.rssin.listener.RealtimeListener;
import org.rssin.rssin.Feed;
import org.rssin.rssin.FeedLoaderAndSorter;
import org.rssin.rssin.R;
@@ -67,24 +68,30 @@ public class NavigationDrawerFeedFragment extends Fragment {
List<Feed> singleFeedList = new ArrayList<Feed>();
singleFeedList.add(feed);
+ final FeedItemAdapter feedItemAdapter = new FeedItemAdapter(new ArrayList<SortedFeedItemContainer>());
+ mRecyclerView.setAdapter(feedItemAdapter);
+ mRecyclerView.setHasFixedSize(true);
+
/**
- * @todo Load feeds in separate thread so that the UI is immediately available
- *
* @todo Now, feed items are only returned after *all* feeds have been loaded. With many
* filters that may take a while, so it would be preferable to return intermediate
* results. We could do this for example with {@link org.rssin.listener.RealtimeListener}
*/
FeedLoaderAndSorter loaderAndSorter = new FeedLoaderAndSorter(singleFeedList);
- loaderAndSorter.getFilteredFeedItems(context, new VolleyFetcher(context), new FallibleListener<List<SortedFeedItemContainer>, VolleyError>() {
+ loaderAndSorter.getFilteredFeedItems(context, VolleyFetcher.getInstance(context), new RealtimeListener<List<SortedFeedItemContainer>, Object>() {
+ @Override
+ public void finish() {
+ // @todo finish
+ }
+
@Override
public void onReceive(List<SortedFeedItemContainer> data) {
- FeedItemAdapter feedItemAdapter = new FeedItemAdapter(data);
- mRecyclerView.setAdapter(feedItemAdapter);
- mRecyclerView.setHasFixedSize(true);
+ feedItemAdapter.feedItems = data;
+ feedItemAdapter.notifyDataSetChanged();
}
@Override
- public void onError(VolleyError error) {
+ public void onError(Object error) {
Frontend.error(context, R.string.error_net_load);
}
});
diff --git a/app/src/main/java/org/rssin/android/NavigationDrawerFilterFragment.java b/app/src/main/java/org/rssin/android/NavigationDrawerFilterFragment.java
index 74be14a..ececd81 100755
--- a/app/src/main/java/org/rssin/android/NavigationDrawerFilterFragment.java
+++ b/app/src/main/java/org/rssin/android/NavigationDrawerFilterFragment.java
@@ -13,12 +13,14 @@ import android.view.ViewGroup;
import com.android.volley.VolleyError;
import org.rssin.listener.FallibleListener;
+import org.rssin.listener.RealtimeListener;
import org.rssin.rssin.FeedLoaderAndSorter;
import org.rssin.rssin.Filter;
import org.rssin.rssin.R;
import org.rssin.rssin.SortedFeedItemContainer;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -66,24 +68,30 @@ public class NavigationDrawerFilterFragment extends Fragment {
filter.ensureFeeds(DefaultStorageProvider.getInstance(context));
+ final FeedItemAdapter feedItemAdapter = new FeedItemAdapter(new ArrayList<SortedFeedItemContainer>());
+ mRecyclerView.setAdapter(feedItemAdapter);
+ mRecyclerView.setHasFixedSize(true);
+
/**
- * @todo Load feeds in separate thread so that the UI is immediately available
- *
* @todo Now, feed items are only returned after *all* feeds have been loaded. With many
* filters that may take a while, so it would be preferable to return intermediate
* results. We could do this for example with {@link org.rssin.listener.RealtimeListener}
*/
FeedLoaderAndSorter loaderAndSorter = new FeedLoaderAndSorter(filter.getFeeds());
- loaderAndSorter.getFilteredFeedItems(context, new VolleyFetcher(context), new FallibleListener<List<SortedFeedItemContainer>, VolleyError>() {
+ loaderAndSorter.getFilteredFeedItems(context, VolleyFetcher.getInstance(context), new RealtimeListener<List<SortedFeedItemContainer>, Object>() {
+ @Override
+ public void finish() {
+ // @todo finish
+ }
+
@Override
public void onReceive(List<SortedFeedItemContainer> data) {
- FeedItemAdapter feedItemAdapter = new FeedItemAdapter(data);
- mRecyclerView.setAdapter(feedItemAdapter);
- mRecyclerView.setHasFixedSize(true);
+ feedItemAdapter.feedItems = data;
+ feedItemAdapter.notifyDataSetChanged();
}
@Override
- public void onError(VolleyError error) {
+ public void onError(Object error) {
Frontend.error(context, R.string.error_net_load);
}
});
diff --git a/app/src/main/java/org/rssin/android/SharedPreferencesStorageProvider.java b/app/src/main/java/org/rssin/android/SharedPreferencesStorageProvider.java
index dbfcc9a..ffcf0e1 100755
--- a/app/src/main/java/org/rssin/android/SharedPreferencesStorageProvider.java
+++ b/app/src/main/java/org/rssin/android/SharedPreferencesStorageProvider.java
@@ -168,19 +168,6 @@ class SharedPreferencesStorageProvider implements StorageProvider, FilterStorage
@Override
public List<Feed> allFeeds() {
Set<String> names = context.getSharedPreferences(ADMIN_PREF_KEY, Context.MODE_PRIVATE).getStringSet("feeds", new HashSet<String>());
- if (names.isEmpty() && !context.getSharedPreferences(ADMIN_PREF_KEY, Context.MODE_PRIVATE).getBoolean("firstload", false)) {
- String[] feedsList = context.getResources().getStringArray(R.array.default_feeds);
- /*for (String url : feedsList) {
- try {
- Feed f = new Feed(url);
- f.store(this);
- } catch (Exception e) {
- Log.w("SPSP", "Couldn't add " + url, e);
- }
- }*/
- context.getSharedPreferences(ADMIN_PREF_KEY, Context.MODE_PRIVATE).edit().putBoolean("firstload", true).apply();
- names = context.getSharedPreferences(ADMIN_PREF_KEY, Context.MODE_PRIVATE).getStringSet("feeds", new HashSet<String>());
- }
List<Feed> feeds = new ArrayList<>();
for (String name : names) {
Feed feed = getFeed(name);
diff --git a/app/src/main/java/org/rssin/android/VolleyFetcher.java b/app/src/main/java/org/rssin/android/VolleyFetcher.java
index af6895e..9aa7c03 100644
--- a/app/src/main/java/org/rssin/android/VolleyFetcher.java
+++ b/app/src/main/java/org/rssin/android/VolleyFetcher.java
@@ -19,14 +19,22 @@ import org.rssin.listener.Listener;
*/
class VolleyFetcher implements Fetcher {
- private final Context context;
+ private static VolleyFetcher instance;
+
private final RequestQueue requestQueue;
- public VolleyFetcher(Context context) {
- this.context = context;
+ private VolleyFetcher(Context context) {
requestQueue = Volley.newRequestQueue(context);
}
+ public static VolleyFetcher getInstance(Context context) {
+ if (instance == null) {
+ instance = new VolleyFetcher(context);
+ }
+
+ return instance;
+ }
+
@Override
public void fetch(Request request) {
fetch(request, null);
diff --git a/app/src/main/java/org/rssin/listener/RealtimeListener.java b/app/src/main/java/org/rssin/listener/RealtimeListener.java
index 4a2ac3e..cb63b33 100644
--- a/app/src/main/java/org/rssin/listener/RealtimeListener.java
+++ b/app/src/main/java/org/rssin/listener/RealtimeListener.java
@@ -4,6 +4,6 @@ package org.rssin.listener;
* The RealtimeListener lets you call onReceive() multiple times.
* When all data has been sent, call finish().
*/
-public interface RealtimeListener extends Listener {
+public interface RealtimeListener<T,E> extends FallibleListener<T,E> {
void finish();
}
diff --git a/app/src/main/java/org/rssin/neurons/FeedSorter.java b/app/src/main/java/org/rssin/neurons/FeedSorter.java
index 4cd5856..bfd61a1 100755
--- a/app/src/main/java/org/rssin/neurons/FeedSorter.java
+++ b/app/src/main/java/org/rssin/neurons/FeedSorter.java
@@ -25,7 +25,7 @@ public class FeedSorter implements Storable {
private static final long serialVersionUID = 0;
private final SentenceSplitter splitter = new SentenceSplitter();
- private MultiNeuralNetwork nn = new MultiNeuralNetwork(25, 50);
+ private MultiNeuralNetwork nn = new MultiNeuralNetwork(10, 50);
private List<TrainingCase> trainingCases = new ArrayList<>();
private int[] isNthMonthInput = new int[12];
@@ -35,36 +35,6 @@ public class FeedSorter implements Storable {
private Hashtable<String, Integer> wordInputs = new Hashtable<>();
private Hashtable<String, Integer> authorInputs = new Hashtable<>();
- private synchronized void writeObject(java.io.ObjectOutputStream stream) throws IOException {
- stream.writeObject(nn);
- SerializationTools.writeList(trainingCases, stream);
- SerializationTools.writeArray(isNthMonthInput, stream);
- SerializationTools.writeArray(isNthWeekDayInput, stream);
- stream.writeInt(isMorning);
- stream.writeInt(isAfternoon);
- stream.writeInt(isEvening);
- stream.writeInt(isNight);
- stream.writeInt(biasInput);
- stream.writeObject(categoryInputs);
- stream.writeObject(wordInputs);
- stream.writeObject(authorInputs);
- }
-
- private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
- nn = (MultiNeuralNetwork) stream.readObject();
- trainingCases = SerializationTools.readList(stream);
- isNthMonthInput = SerializationTools.readArrayInt(stream);
- isNthWeekDayInput = SerializationTools.readArrayInt(stream);
- isMorning = stream.readInt();
- isAfternoon = stream.readInt();
- isEvening = stream.readInt();
- isNight = stream.readInt();
- biasInput = stream.readInt();
- categoryInputs = (Hashtable<String, Integer>) stream.readObject();
- wordInputs = (Hashtable<String, Integer>) stream.readObject();
- authorInputs = (Hashtable<String, Integer>) stream.readObject();
- }
-
/**
* Initializes a new FeedSorter, and creates the basic inputs for the Neural network.4
*/
@@ -215,16 +185,16 @@ public class FeedSorter implements Storable {
* @param items The list of items.
* @return A new, sorted, list of items.
*/
- public List<SortedFeedItemContainer> sortItems(List<SortedFeedItemContainer> items) {
+ public synchronized void sortItems(List<SortedFeedItemContainer> items) {
final int SECONDS_IN_DAY = 24 * 60 * 60;
for (SortedFeedItemContainer item : items) {
- PredictionInterface prediction = getPrediction(item.getFeeditem());
- item.setScore((long) (item.getFeeditem().getPubDate().getTime() / 1000 + prediction.getOutput() * SECONDS_IN_DAY));
+ if (!item.hasScore()) {
+ PredictionInterface prediction = getPrediction(item.getFeeditem());
+ item.setScore((long) (item.getFeeditem().getPubDate().getTime() / 1000 + prediction.getOutput() * SECONDS_IN_DAY));
+ }
}
Collections.sort(items);
-
- return items;
}
}
diff --git a/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java b/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java
index f7a7099..904591c 100755
--- a/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java
+++ b/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java
@@ -13,14 +13,6 @@ class MultiNeuralNetwork implements Serializable {
private static final long serialVersionUID = 0;
private NeuralNetwork[] networks;
- private synchronized void writeObject(java.io.ObjectOutputStream stream) throws IOException {
- SerializationTools.writeArray(networks, stream);
- }
-
- private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
- networks = SerializationTools.readArray(stream, NeuralNetwork.class);
- }
-
/**
* Creates a new instance of the MultiNeuralNetwork
* @param numNetworks The number of underlying networks.
diff --git a/app/src/main/java/org/rssin/neurons/NeuralNetwork.java b/app/src/main/java/org/rssin/neurons/NeuralNetwork.java
index 2d35247..aa34e4f 100755
--- a/app/src/main/java/org/rssin/neurons/NeuralNetwork.java
+++ b/app/src/main/java/org/rssin/neurons/NeuralNetwork.java
@@ -16,16 +16,6 @@ class NeuralNetwork implements Serializable {
private Neuron[] hiddenNodes;
private Neuron outputNode;
- private synchronized void writeObject(java.io.ObjectOutputStream stream) throws IOException {
- SerializationTools.writeArray(hiddenNodes, stream);
- stream.writeObject(outputNode);
- }
-
- private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
- hiddenNodes = SerializationTools.readArray(stream, Neuron.class);
- outputNode = (Neuron) stream.readObject();
- }
-
/**
* Creates a new instance of the neural network.
* @param numHiddenNodes The number of hidden nodes in the neural network.
diff --git a/app/src/main/java/org/rssin/neurons/Neuron.java b/app/src/main/java/org/rssin/neurons/Neuron.java
index 52fcdba..6b8b76e 100755
--- a/app/src/main/java/org/rssin/neurons/Neuron.java
+++ b/app/src/main/java/org/rssin/neurons/Neuron.java
@@ -18,15 +18,6 @@ class Neuron implements Serializable {
private List<Double> weights = new ArrayList<>();
- private synchronized void writeObject(java.io.ObjectOutputStream stream) throws IOException {
- SerializationTools.writeList(weights, stream);
- }
-
- private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
- weights = SerializationTools.readList(stream);
- }
-
-
public Neuron() {
}
diff --git a/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java b/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java
index 524ac46..5a08ab7 100755
--- a/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java
+++ b/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java
@@ -34,25 +34,68 @@ public class FeedLoaderAndSorter {
* @param fetcher HTTP Fetcher
* @param listener Listener for when the fetcher finishes
*/
- public void getFilteredFeedItems(Context context, Fetcher fetcher, final Listener<List<SortedFeedItemContainer>> listener)
- {
+ public void getFilteredFeedItems(
+ Context context,
+ Fetcher fetcher,
+ final RealtimeListener<List<SortedFeedItemContainer>, Object> listener) {
final List<SortedFeedItemContainer> resultingItems = new ArrayList<>();
final Counter counter = new Counter(feeds.size());
final FeedSorter sorter = FeedSorterProvider.getInstance(context).getFeedSorter();
for (Feed feed : feeds) {
+ Loader loader = new Loader(
+ feed,
+ fetcher,
+ listener,
+ resultingItems,
+ counter,
+ sorter
+ );
+ Thread thread = new Thread(loader);
+ thread.start();
+ }
+ }
+
+ private static class Loader implements Runnable {
+
+ final private Feed feed;
+ final private Fetcher fetcher;
+ final private RealtimeListener<List<SortedFeedItemContainer>,Object> listener;
+ final private List<SortedFeedItemContainer> resultingItems;
+ final private Counter counter;
+ final private FeedSorter feedSorter;
+
+ public Loader(
+ Feed feed,
+ Fetcher fetcher,
+ RealtimeListener<List<SortedFeedItemContainer>,Object> listener,
+ List<SortedFeedItemContainer> resultingItems,
+ Counter counter,
+ FeedSorter feedSorter) {
+ this.feed = feed;
+ this.fetcher = fetcher;
+ this.listener = listener;
+ this.resultingItems = resultingItems;
+ this.counter = counter;
+ this.feedSorter = feedSorter;
+ }
+
+ @Override
+ public void run() {
final FeedLoader loader = new FeedLoader(feed.getURL());
loader.fetchXML(fetcher, new FallibleListener<Object, Object>() {
@Override
public void onReceive(Object data) {
- for (FeedItem item : loader.getFeed().getPosts()) {
- resultingItems.add(new SortedFeedItemContainer(item));
+ List<FeedItem> feedItems = loader.getFeed().getPosts();
+ synchronized (resultingItems) {
+ for (FeedItem item : feedItems) {
+ resultingItems.add(new SortedFeedItemContainer(item));
+ }
+ feedSorter.sortItems(resultingItems);
}
- List<SortedFeedItemContainer> sorted = sorter.sortItems(resultingItems);
-
if (counter.decr().isZero() || listener.getClass() == RealtimeListener.class) {
- listener.onReceive(sorted);
+ listener.onReceive(resultingItems);
if (counter.decr().isZero() && listener.getClass() == RealtimeListener.class) {
((RealtimeListener) listener).finish();
}
@@ -61,9 +104,7 @@ public class FeedLoaderAndSorter {
@Override
public void onError(Object error) {
- try {
- ((FallibleListener) listener).onError(error);
- } catch (ClassCastException e) {}
+ listener.onError(error);
}
});
}
diff --git a/app/src/main/java/org/rssin/rssin/SortedFeedItemContainer.java b/app/src/main/java/org/rssin/rssin/SortedFeedItemContainer.java
index f96382a..af5d35a 100755
--- a/app/src/main/java/org/rssin/rssin/SortedFeedItemContainer.java
+++ b/app/src/main/java/org/rssin/rssin/SortedFeedItemContainer.java
@@ -3,8 +3,6 @@ package org.rssin.rssin;
import android.content.Context;
import org.rssin.android.FeedSorterProvider;
-import org.rssin.android.FiltersList;
-import org.rssin.neurons.FeedSorter;
import org.rssin.neurons.Feedback;
import org.rssin.neurons.TrainingCase;
import org.rssin.rss.FeedItem;
@@ -16,25 +14,24 @@ import java.io.Serializable;
*/
public class SortedFeedItemContainer implements Comparable<SortedFeedItemContainer>, Serializable {
private FeedItem feeditem;
- private long score;
+
+ private long score = -1;
private TrainingCase trainingCase;
public SortedFeedItemContainer(FeedItem feeditem)
{
this.feeditem = feeditem;
- this.setScore(-1);
}
public FeedItem getFeeditem() {
return feeditem;
}
- public long getScore() {
- if(score == -1)
- {
- throw new UnsupportedOperationException("score not set");
- }
+ public boolean hasScore() {
+ return score != 0;
+ }
+ public long getScore() {
return score;
}
diff --git a/app/src/main/res/values/feeds.xml b/app/src/main/res/values/feeds.xml
index e4ae386..384739b 100644
--- a/app/src/main/res/values/feeds.xml
+++ b/app/src/main/res/values/feeds.xml
@@ -1,86 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="default_feeds">
- <item>http://feeds.bbci.co.uk/news/business/rss.xml</item>
- <item>http://feeds.bbci.co.uk/news/entertainment_and_arts/rss.xml</item>
- <item>http://feeds.bbci.co.uk/news/health/rss.xml</item>
<item>http://feeds.bbci.co.uk/news/politics/rss.xml</item>
<item>http://feeds.bbci.co.uk/news/science_and_environment/rss.xml</item>
<item>http://feeds.bbci.co.uk/news/technology/rss.xml</item>
- <item>http://feeds.bbci.co.uk/news/uk/rss.xml</item>
<item>http://feeds.bbci.co.uk/news/world/rss.xml</item>
<item>http://feeds.bbci.co.uk/sport/0/rss.xml</item>
- <item>http://feeds.foxnews.com/foxnews/internal/travel/mixed</item>
- <item>http://feeds.foxnews.com/foxnews/opinion</item>
<item>http://feeds.foxnews.com/foxnews/politics</item>
<item>http://feeds.foxnews.com/foxnews/science</item>
- <item>http://feeds.foxnews.com/foxnews/section/lifestyle</item>
<item>http://feeds.foxnews.com/foxnews/sports</item>
<item>http://feeds.foxnews.com/foxnews/tech</item>
- <item>http://feeds.mashable.com/mashable/business</item>
- <item>http://feeds.mashable.com/mashable/entertainment</item>
- <item>http://feeds.mashable.com/mashable/socialmedia</item>
- <item>http://feeds.mashable.com/mashable/tech</item>
- <item>http://feeds.reuters.com/news/artsculture</item>
- <item>http://feeds.reuters.com/news/economy</item>
- <item>http://feeds.reuters.com/news/reutersmedia</item>
- <item>http://feeds.reuters.com/news/wealth</item>
- <item>http://feeds.reuters.com/reuters/businessNews</item>
- <item>http://feeds.reuters.com/reuters/entertainment</item>
<item>http://feeds.reuters.com/reuters/environment</item>
<item>http://feeds.reuters.com/reuters/financialsNews</item>
- <item>http://feeds.reuters.com/reuters/healthNews</item>
- <item>http://feeds.reuters.com/reuters/hotStocksNews</item>
- <item>http://feeds.reuters.com/reuters/lifestyle</item>
- <item>http://feeds.reuters.com/reuters/oddlyEnoughNews</item>
- <item>http://feeds.reuters.com/Reuters/PoliticsNews</item>
- <item>http://feeds.reuters.com/reuters/scienceNews</item>
- <item>http://feeds.reuters.com/reuters/sportsNews</item>
- <item>http://feeds.reuters.com/reuters/technologyNews</item>
- <item>http://feeds.reuters.com/reuters/technologysectorNews</item>
- <item>http://feeds.reuters.com/reuters/UShealthcareNews</item>
<item>http://feeds.reuters.com/reuters/worldNews</item>
- <item>http://rss.cnn.com/rss/edition_entertainment.rss</item>
- <item>http://rss.cnn.com/rss/edition_space.rss</item>
- <item>http://rss.cnn.com/rss/edition_sport.rss</item>
- <item>http://rss.cnn.com/rss/edition_technology.rss</item>
- <item>http://rss.cnn.com/rss/money_news_international.rss</item>
- <item>http://rss.cnn.com/rss/si_topstories.rss</item>
- <item>http://rss.nytimes.com/services/xml/rss/nyt/Books.xml</item>
- <item>http://rss.nytimes.com/services/xml/rss/nyt/Business.xml</item>
- <item>http://rss.nytimes.com/services/xml/rss/nyt/Dance.xml</item>
- <item>http://rss.nytimes.com/services/xml/rss/nyt/Economy.xml</item>
<item>http://rss.nytimes.com/services/xml/rss/nyt/Environment.xml</item>
- <item>http://rss.nytimes.com/services/xml/rss/nyt/FashionandStyle.xml</item>
- <item>http://rss.nytimes.com/services/xml/rss/nyt/MediaandAdvertising.xml</item>
- <item>http://rss.nytimes.com/services/xml/rss/nyt/Movies.xml</item>
<item>http://rss.nytimes.com/services/xml/rss/nyt/Music.xml</item>
- <item>http://rss.nytimes.com/services/xml/rss/nyt/Science.xml</item>
- <item>http://rss.nytimes.com/services/xml/rss/nyt/Sports.xml</item>
- <item>http://rss.nytimes.com/services/xml/rss/nyt/Technology.xml</item>
<item>http://rss.nytimes.com/services/xml/rss/nyt/Travel.xml</item>
- <item>http://www.cnet.com/rss/news/</item>
- <item>http://www.dailymail.co.uk/health/index.rss</item>
- <item>http://www.dailymail.co.uk/money/index.rss</item>
- <item>http://www.dailymail.co.uk/sciencetech/index.rss</item>
- <item>http://www.dailymail.co.uk/sport/index.rss</item>
- <item>http://www.dailymail.co.uk/tvshowbiz/index.rss</item>
- <item>http://www.thesundaily.my/rss/business</item>
- <item>http://www.thesundaily.my/rss/lifestyle/food</item>
- <item>http://www.thesundaily.my/rss/lifestyle/health</item>
- <item>http://www.thesundaily.my/rss/lifestyle/tech</item>
- <item>http://www.thesundaily.my/rss/lifestyle/travel</item>
- <item>http://www.thesundaily.my/rss/media-marketing</item>
- <item>http://www.thesundaily.my/rss/opinion</item>
- <item>http://www.thesundaily.my/rss/showbiz</item>
- <item>http://www.thesundaily.my/rss/sports</item>
- <item>http://www.thesundaily.my/rss/style</item>
- <item>http://www.washingtontimes.com/rss/headlines/culture/autos/</item>
- <item>http://www.washingtontimes.com/rss/headlines/culture/entertainment/</item>
- <item>http://www.washingtontimes.com/rss/headlines/culture/health/</item>
- <item>http://www.washingtontimes.com/rss/headlines/culture/travel/</item>
- <item>http://www.washingtontimes.com/rss/headlines/news/politics/</item>
- <item>http://www.washingtontimes.com/rss/headlines/opinion/</item>
- <item>http://www.washingtontimes.com/rss/headlines/sports/</item>
</string-array>
</resources> \ No newline at end of file