Use nucleus restartables in chapters presenter. Fix some database methods. Add swipe refresh to chapters fragment. Use Icepick library.

This commit is contained in:
inorichi 2015-10-18 19:18:50 +02:00
parent 920a71601b
commit 1719959bc8
10 changed files with 105 additions and 42 deletions

View file

@ -49,6 +49,7 @@ dependencies {
final MOCKITO_VERSION = '1.10.19'
final STORIO_VERSION = '1.4.0'
final NUCLEUS_VERSION = '2.0.1'
final ICEPICK_VERSION = '3.1.0'
compile fileTree(dir: 'libs', include: ['*.jar'])
@ -75,6 +76,8 @@ dependencies {
compile 'com.jakewharton.timber:timber:3.1.0'
compile 'uk.co.ribot:easyadapter:1.5.0@aar'
compile 'ch.acra:acra:4.6.2'
compile "frankiesardo:icepick:$ICEPICK_VERSION"
provided "frankiesardo:icepick-processor:$ICEPICK_VERSION"
compile "com.google.dagger:dagger:$DAGGER_VERSION"
apt "com.google.dagger:dagger-compiler:$DAGGER_VERSION"

View file

@ -93,4 +93,11 @@
-keep public class * extends android.support.v4.view.ActionProvider {
public <init>(android.content.Context);
}
# Icepick
-dontwarn icepick.**
-keep class **$$Icepick { *; }
-keepclasseswithmembernames class * {
@icepick.* <fields>;
}

View file

@ -7,6 +7,7 @@ import com.pushtorefresh.storio.sqlite.StorIOSQLite;
import com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite;
import com.pushtorefresh.storio.sqlite.operations.delete.DeleteResult;
import com.pushtorefresh.storio.sqlite.operations.delete.DeleteResults;
import com.pushtorefresh.storio.sqlite.operations.post.PostResult;
import com.pushtorefresh.storio.sqlite.operations.put.PutResult;
import com.pushtorefresh.storio.sqlite.operations.put.PutResults;
@ -73,7 +74,7 @@ public class DatabaseHelper implements MangaManager, ChapterManager {
}
@Override
public Observable insertOrRemoveChapters(Manga manga, List<Chapter> chapters) {
public Observable<PostResult> insertOrRemoveChapters(Manga manga, List<Chapter> chapters) {
return mChapterManager.insertOrRemoveChapters(manga, chapters);
}

View file

@ -2,6 +2,7 @@ package eu.kanade.mangafeed.data.managers;
import com.pushtorefresh.storio.sqlite.operations.delete.DeleteResult;
import com.pushtorefresh.storio.sqlite.operations.delete.DeleteResults;
import com.pushtorefresh.storio.sqlite.operations.post.PostResult;
import com.pushtorefresh.storio.sqlite.operations.put.PutResult;
import com.pushtorefresh.storio.sqlite.operations.put.PutResults;
@ -21,7 +22,7 @@ public interface ChapterManager {
Observable<PutResults<Chapter>> insertChapters(List<Chapter> chapters);
Observable insertOrRemoveChapters(Manga manga, List<Chapter> chapters);
Observable<PostResult> insertOrRemoveChapters(Manga manga, List<Chapter> chapters);
Observable<DeleteResult> deleteChapter(Chapter chapter);

View file

@ -70,6 +70,10 @@ public class ChapterManagerImpl extends BaseManager implements ChapterManager {
// Add new chapters or delete if the source deletes them
@Override
public Observable<PostResult> insertOrRemoveChapters(Manga manga, List<Chapter> chapters) {
for (Chapter chapter : chapters) {
chapter.manga_id = manga.id;
}
Observable<List<Chapter>> chapterList = Observable.create(subscriber -> {
subscriber.onNext(prepareGetChapters(manga).executeAsBlocking());
subscriber.onCompleted();

View file

@ -1,11 +1,27 @@
package eu.kanade.mangafeed.presenter;
import android.os.Bundle;
import android.support.annotation.NonNull;
import de.greenrobot.event.EventBus;
import icepick.Icepick;
import nucleus.presenter.RxPresenter;
import nucleus.view.ViewWithPresenter;
public class BasePresenter<V extends ViewWithPresenter> extends RxPresenter<V> {
@Override
protected void onCreate(Bundle savedState) {
super.onCreate(savedState);
Icepick.restoreInstanceState(this, savedState);
}
@Override
protected void onSave(@NonNull Bundle state) {
super.onSave(state);
Icepick.saveInstanceState(this, state);
}
public void registerForStickyEvents() {
EventBus.getDefault().registerSticky(this);
}

View file

@ -1,15 +1,22 @@
package eu.kanade.mangafeed.presenter;
import android.os.Bundle;
import com.pushtorefresh.storio.sqlite.operations.post.PostResult;
import java.util.List;
import javax.inject.Inject;
import eu.kanade.mangafeed.data.helpers.DatabaseHelper;
import eu.kanade.mangafeed.data.helpers.SourceManager;
import eu.kanade.mangafeed.data.models.Chapter;
import eu.kanade.mangafeed.data.models.Manga;
import eu.kanade.mangafeed.sources.Source;
import eu.kanade.mangafeed.ui.fragment.MangaChaptersFragment;
import rx.Subscription;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import timber.log.Timber;
public class MangaChaptersPresenter extends BasePresenter<MangaChaptersFragment> {
@ -17,9 +24,24 @@ public class MangaChaptersPresenter extends BasePresenter<MangaChaptersFragment>
@Inject SourceManager sourceManager;
private Manga manga;
private Subscription chaptersSubscription;
private Subscription onlineChaptersSubscription;
private boolean doingRequest = false;
private static final int DB_CHAPTERS = 1;
private static final int ONLINE_CHAPTERS = 2;
@Override
protected void onCreate(Bundle savedState) {
super.onCreate(savedState);
restartableLatestCache(DB_CHAPTERS,
this::getDbChaptersObs,
MangaChaptersFragment::onNextChapters
);
restartableLatestCache(ONLINE_CHAPTERS,
this::getOnlineChaptersObs,
(view, result) -> view.onNextOnlineChapters()
);
}
@Override
protected void onTakeView(MangaChaptersFragment view) {
@ -34,43 +56,30 @@ public class MangaChaptersPresenter extends BasePresenter<MangaChaptersFragment>
}
public void onEventMainThread(Manga manga) {
this.manga = manga;
getChapters();
if (this.manga == null) {
this.manga = manga;
start(DB_CHAPTERS);
}
}
public void refreshChapters() {
if (manga != null && !doingRequest)
getChaptersFromSource(manga);
public void refreshChapters(MangaChaptersFragment view) {
if (manga != null) {
view.setSwipeRefreshing();
start(ONLINE_CHAPTERS);
}
}
public void getChapters() {
if (chaptersSubscription != null)
return;
add(chaptersSubscription = db.getChapters(manga.id)
private Observable<List<Chapter>> getDbChaptersObs() {
return db.getChapters(manga.id)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.compose(deliverLatestCache())
.subscribe(this.split(MangaChaptersFragment::onNextChapters)));
.observeOn(AndroidSchedulers.mainThread());
}
public void getChaptersFromSource(Manga manga) {
if (onlineChaptersSubscription != null)
remove(onlineChaptersSubscription);
Source source = sourceManager.get(manga.source);
doingRequest = true;
onlineChaptersSubscription = source.pullChaptersFromNetwork(manga.url)
private Observable<PostResult> getOnlineChaptersObs() {
return sourceManager.get(manga.source)
.pullChaptersFromNetwork(manga.url)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.compose(deliverLatestCache())
.subscribe(this.split((view, chapters) -> {
doingRequest = false;
}), throwable -> {
doingRequest = false;
});
add(onlineChaptersSubscription);
.flatMap(chapters -> db.insertOrRemoveChapters(manga, chapters))
.observeOn(AndroidSchedulers.mainThread());
}
}

View file

@ -2,6 +2,7 @@ package eu.kanade.mangafeed.ui.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
@ -26,6 +27,7 @@ import uk.co.ribot.easyadapter.EasyRecyclerAdapter;
public class MangaChaptersFragment extends BaseFragment<MangaChaptersPresenter> {
@Bind(R.id.chapter_list) RecyclerView chapters;
@Bind(R.id.swipe_refresh) SwipeRefreshLayout swipe_refresh;
private EasyRecyclerAdapter<Chapter> adapter;
@ -48,6 +50,7 @@ public class MangaChaptersFragment extends BaseFragment<MangaChaptersPresenter>
chapters.setLayoutManager(new LinearLayoutManager(getActivity()));
createAdapter();
setSwipeRefreshListener();
return view;
}
@ -62,7 +65,7 @@ public class MangaChaptersFragment extends BaseFragment<MangaChaptersPresenter>
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_refresh:
getPresenter().refreshChapters();
getPresenter().refreshChapters(this);
break;
}
return super.onOptionsItemSelected(item);
@ -73,8 +76,19 @@ public class MangaChaptersFragment extends BaseFragment<MangaChaptersPresenter>
chapters.setAdapter(adapter);
}
private void setSwipeRefreshListener() {
swipe_refresh.setOnRefreshListener(() -> getPresenter().refreshChapters(this));
}
public void onNextChapters(List<Chapter> chapters) {
adapter.setItems(chapters);
}
public void onNextOnlineChapters() {
swipe_refresh.setRefreshing(false);
}
public void setSwipeRefreshing() {
swipe_refresh.setRefreshing(true);
}
}

View file

@ -3,11 +3,18 @@
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/chapter_list">
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/chapter_list">
</android.support.v7.widget.RecyclerView>
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>

View file

@ -16,5 +16,6 @@ buildscript {
allprojects {
repositories {
jcenter()
maven {url "https://clojars.org/repo/"}
}
}