Backport to Java 6...

Android Studio automatically folds lambda-style, so it won't get too out of hand.
Rx/Retrolambda
Bradlee Speice 2014-06-14 16:41:11 -04:00
parent e945ef51a7
commit 4269988b7c
7 changed files with 148 additions and 54 deletions

View File

@ -1,6 +1,6 @@
apply plugin: 'android'
apply plugin: 'android-apt'
apply plugin: 'retrolambda'
//apply plugin: 'retrolambda'
buildscript {
repositories {
@ -8,7 +8,7 @@ buildscript {
}
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.3'
classpath 'me.tatarka:gradle-retrolambda:1.3.2'
//classpath 'me.tatarka:gradle-retrolambda:1.3.2'
}
}
@ -75,10 +75,14 @@ android {
lintOptions {
abortOnError false
}
/*
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
*/
defaultConfig {}
productFlavors {
}

View File

@ -21,6 +21,8 @@ import butterknife.InjectView;
import butterknife.OnClick;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.functions.Func1;
/**
* Created by bspeice on 5/20/14.
@ -59,8 +61,18 @@ public class BookItemHolder {
//TODO: Refactor
subscription = bookDownloadManager.getDownloadEvents()
.observeOn(AndroidSchedulers.mainThread())
.filter((event) -> event.getB().getInitials().equals(b.getInitials()))
.subscribe((event) -> displayProgress((int) event.toCircular()));
.filter(new Func1<DLProgressEvent, Boolean>() {
@Override
public Boolean call(DLProgressEvent event) {
return event.getB().getInitials().equals(b.getInitials());
}
})
.subscribe(new Action1<DLProgressEvent>() {
@Override
public void call(DLProgressEvent event) {
BookItemHolder.this.displayProgress((int) event.toCircular());
}
});
}
private void displayInstalled() {

View File

@ -15,15 +15,21 @@ import org.bspeice.minimalbible.MinimalBible;
import org.bspeice.minimalbible.R;
import org.bspeice.minimalbible.activities.BaseFragment;
import org.bspeice.minimalbible.activities.downloader.manager.RefreshManager;
import org.crosswire.jsword.book.Book;
import org.crosswire.jsword.book.BookCategory;
import org.crosswire.jsword.book.BookComparators;
import java.util.List;
import javax.inject.Inject;
import butterknife.ButterKnife;
import butterknife.InjectView;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.functions.Func2;
/**
* A placeholder fragment containing a simple view.
@ -119,22 +125,35 @@ public class BookListFragment extends BaseFragment {
// Listen for the books!
refreshManager.getAvailableModulesFlattened()
.filter((book) -> book.getBookCategory() ==
BookCategory.fromString(getArguments().getString(ARG_BOOK_CATEGORY)))
// Repack all the books
.toSortedList((book1, book2) ->
BookComparators.getInitialComparator().compare(book1, book2))
.observeOn(AndroidSchedulers.mainThread())
.subscribe((books) -> {
downloadsAvailable.setAdapter(new BookListAdapter(inflater, books));
if (getActivity() != null) {
// On a screen rotate, getActivity() will be null. But, the activity will
// already have been set up correctly, so we don't need to worry about it.
// If not null, we need to set it up now.
setInsets(getActivity(), downloadsAvailable);
.filter(new Func1<Book, Boolean>() {
@Override
public Boolean call(Book book) {
return book.getBookCategory() ==
BookCategory.fromString(BookListFragment.this.getArguments()
.getString(ARG_BOOK_CATEGORY));
}
if (refreshDialog != null) {
refreshDialog.cancel();
})
// Repack all the books
.toSortedList(new Func2<Book, Book, Integer>() {
@Override
public Integer call(Book book1, Book book2) {
return BookComparators.getInitialComparator().compare(book1, book2);
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<List<Book>>() {
@Override
public void call(List<Book> books) {
downloadsAvailable.setAdapter(new BookListAdapter(inflater, books));
if (BookListFragment.this.getActivity() != null) {
// On a screen rotate, getActivity() will be null. But, the activity will
// already have been set up correctly, so we don't need to worry about it.
// If not null, we need to set it up now.
setInsets(BookListFragment.this.getActivity(), downloadsAvailable);
}
if (refreshDialog != null) {
refreshDialog.cancel();
}
}
});
}

View File

@ -5,9 +5,11 @@ import android.util.Log;
import org.bspeice.minimalbible.MinimalBible;
import org.crosswire.jsword.book.Book;
import org.crosswire.jsword.book.install.InstallException;
import org.crosswire.jsword.book.install.Installer;
import javax.inject.Inject;
import rx.functions.Action1;
import rx.schedulers.Schedulers;
/**
@ -33,14 +35,18 @@ public class BookDownloadThread {
// First, look up where the Book came from
refreshManager.installerFromBook(b)
.subscribeOn(Schedulers.io())
.subscribe((installer) -> {
try {
installer.install(b);
} catch (InstallException e) {
Log.d(TAG, e.getMessage());
}
.subscribe(new Action1<Installer>() {
@Override
public void call(Installer installer) {
try {
installer.install(b);
} catch (InstallException e) {
Log.d(TAG, e.getMessage());
}
bookDownloadManager.getDownloadEvents().onNext(new DLProgressEvent(DLProgressEvent.PROGRESS_BEGINNING, b));
bookDownloadManager.getDownloadEvents()
.onNext(new DLProgressEvent(DLProgressEvent.PROGRESS_BEGINNING, b));
}
});
}

View File

@ -66,13 +66,16 @@ public class InstalledManager implements BooksListener {
if (installedBooks == null) {
initialize();
}
try {
// This worked in the past, but isn't now...
// installedBooks.remove(b);
Book realBook = installedBooks.getBook(b.getInitials());
b.getDriver().delete(realBook);
} catch (BookException e) {
Log.e("InstalledManager", "Unable to remove book (already uninstalled?): " + e.getLocalizedMessage());
// Not sure why we need to call this multiple times, but...
while (Books.installed().getBooks().contains(b)) {
try {
// This worked in the past, but isn't now...
// installedBooks.remove(b);
Book realBook = installedBooks.getBook(b.getInitials());
b.getDriver().delete(realBook);
} catch (BookException e) {
Log.e("InstalledManager", "Unable to remove book (already uninstalled?): " + e.getLocalizedMessage());
}
}
}
}

View File

@ -14,6 +14,10 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import rx.Observable;
import rx.functions.Action0;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.functions.Func2;
import rx.schedulers.Schedulers;
/**
@ -44,16 +48,30 @@ public class RefreshManager {
private void refreshModules() {
if (availableModules == null) {
availableModules = Observable.from(downloadManager.getInstallers().values())
.map(installer -> {
Map<Installer, List<Book>> map = new HashMap<Installer, List<Book>>();
map.put(installer, installer.getBooks());
return map;
.map(new Func1<Installer, Map<Installer, List<Book>>>() {
@Override
public Map<Installer, List<Book>> call(Installer installer) {
Map<Installer, List<Book>> map = new HashMap<Installer, List<Book>>();
map.put(installer, installer.getBooks());
return map;
}
}).subscribeOn(Schedulers.io())
.cache();
// Set refresh complete when it is.
availableModules.observeOn(Schedulers.io())
.subscribe((onNext) -> {}, (onError) -> {}, () -> refreshComplete.set(true));
.subscribe(new Action1<Map<Installer, List<Book>>>() {
@Override
public void call(Map<Installer, List<Book>> onNext) {}
}, new Action1<Throwable>() {
@Override
public void call(Throwable onError) {}
}, new Action0() {
@Override
public void call() {
refreshComplete.set(true);
}
});
}
}
@ -64,9 +82,19 @@ public class RefreshManager {
public Observable<Book> getAvailableModulesFlattened() {
return availableModules
// First flatten the Map to its lists
.flatMap((books) -> Observable.from(books.values()))
.flatMap(new Func1<Map<Installer, List<Book>>, Observable<? extends List<Book>>>() {
@Override
public Observable<? extends List<Book>> call(Map<Installer, List<Book>> books) {
return Observable.from(books.values());
}
})
// Then flatten the lists
.flatMap(Observable::from);
.flatMap(new Func1<List<Book>, Observable<? extends Book>>() {
@Override
public Observable<? extends Book> call(List<Book> t1) {
return Observable.from(t1);
}
});
}
/**
@ -74,12 +102,16 @@ public class RefreshManager {
* @return The cached book list, or null
*/
public List<Book> getBookList() {
List<Book> availableList = new ArrayList<>();
availableModules.reduce(availableList, (books, installerListMap) -> {
for (List<Book> l : installerListMap.values()) {
books.addAll(l);
List<Book> availableList = new ArrayList<Book>();
availableModules.reduce(availableList,
new Func2<List<Book>, Map<Installer, List<Book>>, List<Book>>() {
@Override
public List<Book> call(List<Book> books, Map<Installer, List<Book>> installerListMap) {
for (List<Book> l : installerListMap.values()) {
books.addAll(l);
}
return books;
}
return books;
});
return availableList;
}
@ -89,17 +121,25 @@ public class RefreshManager {
* @param b The book to search for
* @return The Installer that should be used for this book.
*/
public Observable<Installer> installerFromBook(Book b) {
return availableModules.filter(installerListMap -> {
for (List<Book> element : installerListMap.values()) {
if (element.contains(b)) {
return true;
public Observable<Installer> installerFromBook(final Book b) {
return availableModules.filter(new Func1<Map<Installer, List<Book>>, Boolean>() {
@Override
public Boolean call(Map<Installer, List<Book>> installerListMap) {
for (List<Book> element : installerListMap.values()) {
if (element.contains(b)) {
return true;
}
}
return false;
}
return false;
})
.first()
.map(element -> element.entrySet().iterator().next().getKey());
.map(new Func1<Map<Installer, List<Book>>, Installer>() {
@Override
public Installer call(Map<Installer, List<Book>> element) {
return element.entrySet().iterator().next().getKey();
}
});
}
public boolean isRefreshComplete() {

View File

@ -67,7 +67,12 @@ public class DownloadActivityTest extends InstrumentationTestCase {
final Book testBook = i.getBooks().get(0);
bdm.installBook(testBook);
await().atMost(30, TimeUnit.SECONDS)
.until(() -> Books.installed().getBooks().contains(testBook));
.until(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return Books.installed().getBooks().contains(testBook);
}
});
// Validate that we can actually do something with the book
// TODO: Validate that the book exists on the filesystem too
@ -83,7 +88,12 @@ public class DownloadActivityTest extends InstrumentationTestCase {
// TODO: Validate that the book is off the filesystem
im.removeBook(testBook);
await().atMost(10, TimeUnit.SECONDS)
.until(() -> !Books.installed().getBooks().contains(testBook));
.until(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return !Books.installed().getBooks().contains(testBook);
}
});
}
}