Use nucleus restartables in chapters presenter. Fix some database methods. Add swipe refresh to chapters fragment. Use Icepick library.
This commit is contained in:
parent
920a71601b
commit
1719959bc8
10 changed files with 105 additions and 42 deletions
|
@ -49,6 +49,7 @@ dependencies {
|
||||||
final MOCKITO_VERSION = '1.10.19'
|
final MOCKITO_VERSION = '1.10.19'
|
||||||
final STORIO_VERSION = '1.4.0'
|
final STORIO_VERSION = '1.4.0'
|
||||||
final NUCLEUS_VERSION = '2.0.1'
|
final NUCLEUS_VERSION = '2.0.1'
|
||||||
|
final ICEPICK_VERSION = '3.1.0'
|
||||||
|
|
||||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
|
||||||
|
@ -75,6 +76,8 @@ dependencies {
|
||||||
compile 'com.jakewharton.timber:timber:3.1.0'
|
compile 'com.jakewharton.timber:timber:3.1.0'
|
||||||
compile 'uk.co.ribot:easyadapter:1.5.0@aar'
|
compile 'uk.co.ribot:easyadapter:1.5.0@aar'
|
||||||
compile 'ch.acra:acra:4.6.2'
|
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"
|
compile "com.google.dagger:dagger:$DAGGER_VERSION"
|
||||||
apt "com.google.dagger:dagger-compiler:$DAGGER_VERSION"
|
apt "com.google.dagger:dagger-compiler:$DAGGER_VERSION"
|
||||||
|
|
7
app/proguard-rules.pro
vendored
7
app/proguard-rules.pro
vendored
|
@ -94,3 +94,10 @@
|
||||||
-keep public class * extends android.support.v4.view.ActionProvider {
|
-keep public class * extends android.support.v4.view.ActionProvider {
|
||||||
public <init>(android.content.Context);
|
public <init>(android.content.Context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Icepick
|
||||||
|
-dontwarn icepick.**
|
||||||
|
-keep class **$$Icepick { *; }
|
||||||
|
-keepclasseswithmembernames class * {
|
||||||
|
@icepick.* <fields>;
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import com.pushtorefresh.storio.sqlite.StorIOSQLite;
|
||||||
import com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite;
|
import com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite;
|
||||||
import com.pushtorefresh.storio.sqlite.operations.delete.DeleteResult;
|
import com.pushtorefresh.storio.sqlite.operations.delete.DeleteResult;
|
||||||
import com.pushtorefresh.storio.sqlite.operations.delete.DeleteResults;
|
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.PutResult;
|
||||||
import com.pushtorefresh.storio.sqlite.operations.put.PutResults;
|
import com.pushtorefresh.storio.sqlite.operations.put.PutResults;
|
||||||
|
|
||||||
|
@ -73,7 +74,7 @@ public class DatabaseHelper implements MangaManager, ChapterManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Observable insertOrRemoveChapters(Manga manga, List<Chapter> chapters) {
|
public Observable<PostResult> insertOrRemoveChapters(Manga manga, List<Chapter> chapters) {
|
||||||
return mChapterManager.insertOrRemoveChapters(manga, chapters);
|
return mChapterManager.insertOrRemoveChapters(manga, chapters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.DeleteResult;
|
||||||
import com.pushtorefresh.storio.sqlite.operations.delete.DeleteResults;
|
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.PutResult;
|
||||||
import com.pushtorefresh.storio.sqlite.operations.put.PutResults;
|
import com.pushtorefresh.storio.sqlite.operations.put.PutResults;
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ public interface ChapterManager {
|
||||||
|
|
||||||
Observable<PutResults<Chapter>> insertChapters(List<Chapter> chapters);
|
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);
|
Observable<DeleteResult> deleteChapter(Chapter chapter);
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,10 @@ public class ChapterManagerImpl extends BaseManager implements ChapterManager {
|
||||||
// Add new chapters or delete if the source deletes them
|
// Add new chapters or delete if the source deletes them
|
||||||
@Override
|
@Override
|
||||||
public Observable<PostResult> insertOrRemoveChapters(Manga manga, List<Chapter> chapters) {
|
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 -> {
|
Observable<List<Chapter>> chapterList = Observable.create(subscriber -> {
|
||||||
subscriber.onNext(prepareGetChapters(manga).executeAsBlocking());
|
subscriber.onNext(prepareGetChapters(manga).executeAsBlocking());
|
||||||
subscriber.onCompleted();
|
subscriber.onCompleted();
|
||||||
|
|
|
@ -1,11 +1,27 @@
|
||||||
package eu.kanade.mangafeed.presenter;
|
package eu.kanade.mangafeed.presenter;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
import de.greenrobot.event.EventBus;
|
import de.greenrobot.event.EventBus;
|
||||||
|
import icepick.Icepick;
|
||||||
import nucleus.presenter.RxPresenter;
|
import nucleus.presenter.RxPresenter;
|
||||||
import nucleus.view.ViewWithPresenter;
|
import nucleus.view.ViewWithPresenter;
|
||||||
|
|
||||||
public class BasePresenter<V extends ViewWithPresenter> extends RxPresenter<V> {
|
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() {
|
public void registerForStickyEvents() {
|
||||||
EventBus.getDefault().registerSticky(this);
|
EventBus.getDefault().registerSticky(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,22 @@
|
||||||
package eu.kanade.mangafeed.presenter;
|
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 javax.inject.Inject;
|
||||||
|
|
||||||
import eu.kanade.mangafeed.data.helpers.DatabaseHelper;
|
import eu.kanade.mangafeed.data.helpers.DatabaseHelper;
|
||||||
import eu.kanade.mangafeed.data.helpers.SourceManager;
|
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.data.models.Manga;
|
||||||
import eu.kanade.mangafeed.sources.Source;
|
|
||||||
import eu.kanade.mangafeed.ui.fragment.MangaChaptersFragment;
|
import eu.kanade.mangafeed.ui.fragment.MangaChaptersFragment;
|
||||||
import rx.Subscription;
|
import rx.Observable;
|
||||||
import rx.android.schedulers.AndroidSchedulers;
|
import rx.android.schedulers.AndroidSchedulers;
|
||||||
import rx.schedulers.Schedulers;
|
import rx.schedulers.Schedulers;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class MangaChaptersPresenter extends BasePresenter<MangaChaptersFragment> {
|
public class MangaChaptersPresenter extends BasePresenter<MangaChaptersFragment> {
|
||||||
|
|
||||||
|
@ -17,9 +24,24 @@ public class MangaChaptersPresenter extends BasePresenter<MangaChaptersFragment>
|
||||||
@Inject SourceManager sourceManager;
|
@Inject SourceManager sourceManager;
|
||||||
|
|
||||||
private Manga manga;
|
private Manga manga;
|
||||||
private Subscription chaptersSubscription;
|
|
||||||
private Subscription onlineChaptersSubscription;
|
private static final int DB_CHAPTERS = 1;
|
||||||
private boolean doingRequest = false;
|
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
|
@Override
|
||||||
protected void onTakeView(MangaChaptersFragment view) {
|
protected void onTakeView(MangaChaptersFragment view) {
|
||||||
|
@ -34,43 +56,30 @@ public class MangaChaptersPresenter extends BasePresenter<MangaChaptersFragment>
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onEventMainThread(Manga manga) {
|
public void onEventMainThread(Manga manga) {
|
||||||
|
if (this.manga == null) {
|
||||||
this.manga = manga;
|
this.manga = manga;
|
||||||
getChapters();
|
start(DB_CHAPTERS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshChapters() {
|
public void refreshChapters(MangaChaptersFragment view) {
|
||||||
if (manga != null && !doingRequest)
|
if (manga != null) {
|
||||||
getChaptersFromSource(manga);
|
view.setSwipeRefreshing();
|
||||||
|
start(ONLINE_CHAPTERS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getChapters() {
|
private Observable<List<Chapter>> getDbChaptersObs() {
|
||||||
if (chaptersSubscription != null)
|
return db.getChapters(manga.id)
|
||||||
return;
|
|
||||||
|
|
||||||
add(chaptersSubscription = db.getChapters(manga.id)
|
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread());
|
||||||
.compose(deliverLatestCache())
|
|
||||||
.subscribe(this.split(MangaChaptersFragment::onNextChapters)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getChaptersFromSource(Manga manga) {
|
private Observable<PostResult> getOnlineChaptersObs() {
|
||||||
if (onlineChaptersSubscription != null)
|
return sourceManager.get(manga.source)
|
||||||
remove(onlineChaptersSubscription);
|
.pullChaptersFromNetwork(manga.url)
|
||||||
|
|
||||||
Source source = sourceManager.get(manga.source);
|
|
||||||
doingRequest = true;
|
|
||||||
|
|
||||||
onlineChaptersSubscription = source.pullChaptersFromNetwork(manga.url)
|
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.flatMap(chapters -> db.insertOrRemoveChapters(manga, chapters))
|
||||||
.compose(deliverLatestCache())
|
.observeOn(AndroidSchedulers.mainThread());
|
||||||
.subscribe(this.split((view, chapters) -> {
|
|
||||||
doingRequest = false;
|
|
||||||
}), throwable -> {
|
|
||||||
doingRequest = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
add(onlineChaptersSubscription);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package eu.kanade.mangafeed.ui.fragment;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -26,6 +27,7 @@ import uk.co.ribot.easyadapter.EasyRecyclerAdapter;
|
||||||
public class MangaChaptersFragment extends BaseFragment<MangaChaptersPresenter> {
|
public class MangaChaptersFragment extends BaseFragment<MangaChaptersPresenter> {
|
||||||
|
|
||||||
@Bind(R.id.chapter_list) RecyclerView chapters;
|
@Bind(R.id.chapter_list) RecyclerView chapters;
|
||||||
|
@Bind(R.id.swipe_refresh) SwipeRefreshLayout swipe_refresh;
|
||||||
|
|
||||||
private EasyRecyclerAdapter<Chapter> adapter;
|
private EasyRecyclerAdapter<Chapter> adapter;
|
||||||
|
|
||||||
|
@ -48,6 +50,7 @@ public class MangaChaptersFragment extends BaseFragment<MangaChaptersPresenter>
|
||||||
|
|
||||||
chapters.setLayoutManager(new LinearLayoutManager(getActivity()));
|
chapters.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||||
createAdapter();
|
createAdapter();
|
||||||
|
setSwipeRefreshListener();
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
@ -62,7 +65,7 @@ public class MangaChaptersFragment extends BaseFragment<MangaChaptersPresenter>
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.action_refresh:
|
case R.id.action_refresh:
|
||||||
getPresenter().refreshChapters();
|
getPresenter().refreshChapters(this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
|
@ -73,8 +76,19 @@ public class MangaChaptersFragment extends BaseFragment<MangaChaptersPresenter>
|
||||||
chapters.setAdapter(adapter);
|
chapters.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setSwipeRefreshListener() {
|
||||||
|
swipe_refresh.setOnRefreshListener(() -> getPresenter().refreshChapters(this));
|
||||||
|
}
|
||||||
|
|
||||||
public void onNextChapters(List<Chapter> chapters) {
|
public void onNextChapters(List<Chapter> chapters) {
|
||||||
adapter.setItems(chapters);
|
adapter.setItems(chapters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onNextOnlineChapters() {
|
||||||
|
swipe_refresh.setRefreshing(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSwipeRefreshing() {
|
||||||
|
swipe_refresh.setRefreshing(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,11 @@
|
||||||
android:orientation="vertical" android:layout_width="match_parent"
|
android:orientation="vertical" android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<android.support.v4.widget.SwipeRefreshLayout
|
||||||
|
android:id="@+id/swipe_refresh"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<android.support.v7.widget.RecyclerView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -10,4 +15,6 @@
|
||||||
|
|
||||||
</android.support.v7.widget.RecyclerView>
|
</android.support.v7.widget.RecyclerView>
|
||||||
|
|
||||||
|
</android.support.v4.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -16,5 +16,6 @@ buildscript {
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
|
maven {url "https://clojars.org/repo/"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue