Refactor so we don't re-download the book list every time

Code is still pretty ugly, but I'm not sure on how to prettify it. Get
to that later.
This commit is contained in:
Bradlee Speice 2014-04-23 00:11:13 -04:00
parent 0f98338504
commit e29d4546db
4 changed files with 114 additions and 53 deletions

View File

@ -120,18 +120,17 @@ public class BookListFragment extends Fragment {
f = null;
break;
}
DownloadManager dm = new DownloadManager();
ProgressDialog refreshDialog = new ProgressDialog(getActivity());
if (dm.willRefresh()) {
DownloadManager dm = DownloadManager.getInstance();
if (!dm.isLoaded()) {
ProgressDialog refreshDialog = new ProgressDialog(getActivity());
refreshDialog.setMessage("Refreshing available modules...");
refreshDialog.setCancelable(false);
refreshDialog.show();
dm.fetchAvailableBooks(f, new DlBookRefreshListener(refreshDialog));
} else {
refreshDialog
.setMessage("Fetching available modules from cache...");
dm.fetchAvailableBooks(f, new DlBookRefreshListener(null));
}
refreshDialog.setCancelable(false);
refreshDialog.show();
dm.fetchAvailableBooks(f, new DlBookRefreshListener(refreshDialog));
}
private class DlBookRefreshListener implements

View File

@ -3,29 +3,31 @@ package org.bspeice.minimalbible.activities.downloader;
import java.util.LinkedList;
import java.util.List;
import org.bspeice.minimalbible.MinimalBible;
import org.bspeice.minimalbible.MinimalBibleConstants;
import org.crosswire.jsword.book.Book;
import org.crosswire.jsword.book.BookFilter;
import org.crosswire.jsword.book.install.InstallException;
import org.crosswire.jsword.book.install.Installer;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.util.Log;
public class BookRefreshTask extends AsyncTask<Installer, Integer, List<Book>> {
private static final String TAG = "BookRefreshTask";
private BookRefreshListener listener;
private boolean refresh;
private BookFilter filter;
public BookRefreshTask(boolean refresh, BookRefreshListener listener) {
this.refresh = refresh;
public BookRefreshTask(BookRefreshListener listener) {
this.listener = listener;
}
public BookRefreshTask(boolean refresh, BookFilter f, BookRefreshListener listener) {
this.refresh = refresh;
public BookRefreshTask(BookFilter f,
BookRefreshListener listener) {
this.filter = f;
this.listener = listener;
}
@ -33,35 +35,50 @@ public class BookRefreshTask extends AsyncTask<Installer, Integer, List<Book>> {
@Override
protected List<Book> doInBackground(Installer... params) {
List<Book> books = new LinkedList<Book>();
for (Installer i: params) {
if (refresh) {
for (Installer i : params) {
if (doRefresh()) {
try {
i.reloadBookList();
} catch (InstallException e) {
Log.e(TAG, "Error downloading books from installer: " + i.toString(), e);
Log.e(TAG,
"Error downloading books from installer: "
+ i.toString(), e);
}
}
if (filter != null) {
books.addAll(i.getBooks(filter));
} else {
books.addAll(i.getBooks());
}
}
return books;
}
private boolean doRefresh() {
// Check if we should refresh over the internet, or use the local copy
// TODO: Discover if we need to refresh over Internet, or use a cached
// copy - likely something time-based, also check network state.
// Fun fact - jSword handles the caching for us.
SharedPreferences prefs = MinimalBible.getAppContext()
.getSharedPreferences(
MinimalBibleConstants.DOWNLOAD_PREFS_FILE,
Context.MODE_PRIVATE);
// Refresh if download enabled
return prefs.getBoolean(MinimalBibleConstants.KEY_DOWNLOAD_ENABLED, false);
}
@Override
protected void onPostExecute(List<Book> result) {
super.onPostExecute(result);
listener.onRefreshComplete(result);
}
public interface BookRefreshListener {
public void onRefreshComplete(List<Book> results);
}
}

View File

@ -1,29 +1,36 @@
package org.bspeice.minimalbible.activities.downloader;
import java.util.List;
import java.util.Map;
import org.bspeice.minimalbible.MinimalBible;
import org.bspeice.minimalbible.MinimalBibleConstants;
import org.bspeice.minimalbible.activities.downloader.BookRefreshTask.BookRefreshListener;
import org.crosswire.jsword.book.Book;
import org.crosswire.jsword.book.BookCategory;
import org.crosswire.jsword.book.BookFilter;
import org.crosswire.jsword.book.install.InstallManager;
import org.crosswire.jsword.book.install.Installer;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
public class DownloadManager {
// TODO: Probably should be a singleton.
private final String TAG = "DownloadManager";
private static DownloadManager instance;
private List<Book> books;
public static final BookCategory[] VALID_CATEGORIES = { BookCategory.BIBLE,
BookCategory.COMMENTARY, BookCategory.DICTIONARY,
BookCategory.IMAGES, BookCategory.MAPS };
public DownloadManager() {
public static DownloadManager getInstance() {
if (instance == null) {
instance = new DownloadManager();
}
return instance;
}
private DownloadManager() {
setDownloadDir();
}
@ -31,7 +38,7 @@ public class DownloadManager {
BookRefreshTask.BookRefreshListener bookRefreshListener) {
return _fetchAvailableBooks(null, bookRefreshListener);
}
public BookRefreshTask fetchAvailableBooks(BookFilter f,
BookRefreshTask.BookRefreshListener bookRefreshListener) {
return _fetchAvailableBooks(f, bookRefreshListener);
@ -39,32 +46,30 @@ public class DownloadManager {
private BookRefreshTask _fetchAvailableBooks(BookFilter f,
BookRefreshTask.BookRefreshListener bookRefreshListener) {
Map<String, Installer> installers = getInstallers();
return (BookRefreshTask) new BookRefreshTask(willRefresh(),
bookRefreshListener).execute(installers.values().toArray(
new Installer[installers.size()]));
if (!isLoaded()) {
return (BookRefreshTask) new BookRefreshTask(
new DmBookRefreshListener(bookRefreshListener))
.execute(getInstallersArray());
} else {
return (BookRefreshTask) new NoopBookRefreshTask(books,
bookRefreshListener).execute(getInstallersArray());
}
}
public boolean willRefresh() {
// Method to determine if we need a refresh
// Public, so other modules can predict and take action accordingly.
// TODO: Discover if we need to refresh over Internet, or use a cached
// copy - likely something time-based, also check network state.
// Fun fact - jSword handles the caching for us.
SharedPreferences prefs = MinimalBible.getAppContext()
.getSharedPreferences(
MinimalBibleConstants.DOWNLOAD_PREFS_FILE,
Context.MODE_PRIVATE);
return (prefs.getBoolean(MinimalBibleConstants.KEY_DOWNLOAD_ENABLED, false));
public boolean isLoaded() {
// Let methods know if we're going to take a while to reload everything
return (books != null);
}
public Map<String, Installer> getInstallers() {
return new InstallManager().getInstallers();
}
public Installer[] getInstallersArray() {
Map<String, Installer> installers = getInstallers();
return installers.values().toArray(new Installer[installers.size()]);
}
private void setDownloadDir() {
// We need to set the download directory for jSword to stick with
@ -74,4 +79,19 @@ public class DownloadManager {
System.setProperty("jsword.home", home);
}
// Create our own refresh listener to save a reference to the books
private class DmBookRefreshListener implements BookRefreshListener {
private BookRefreshListener listener;
public DmBookRefreshListener(BookRefreshListener listener) {
this.listener = listener;
}
@Override
public void onRefreshComplete(List<Book> results) {
books = results;
listener.onRefreshComplete(results);
}
}
}

View File

@ -0,0 +1,25 @@
package org.bspeice.minimalbible.activities.downloader;
import java.util.List;
import org.crosswire.jsword.book.Book;
import org.crosswire.jsword.book.install.Installer;
/*
* There's probably a better way of doing this, but this allows me to avoid networking,
* while still maintaining the code structure of being asynchronous.
*/
public class NoopBookRefreshTask extends BookRefreshTask {
BookRefreshListener listener;
List<Book> books;
public NoopBookRefreshTask(List<Book> books, BookRefreshListener listener) {
super(listener);
this.books = books;
}
@Override
protected List<Book> doInBackground(Installer... params) {
return books;
}
}