Begin switch to Nucleus

This commit is contained in:
inorichi 2015-10-16 21:40:59 +02:00
parent 906cdc1348
commit 0cfd433234
4 changed files with 138 additions and 85 deletions

View file

@ -1,6 +1,8 @@
package eu.kanade.mangafeed.presenter; package eu.kanade.mangafeed.presenter;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.widget.ImageView; import android.widget.ImageView;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
@ -12,34 +14,31 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject; import javax.inject.Inject;
import de.greenrobot.event.EventBus; import de.greenrobot.event.EventBus;
import eu.kanade.mangafeed.App;
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.Manga; import eu.kanade.mangafeed.data.models.Manga;
import eu.kanade.mangafeed.sources.Source; import eu.kanade.mangafeed.sources.Source;
import eu.kanade.mangafeed.ui.activity.CatalogueActivity;
import eu.kanade.mangafeed.ui.activity.MangaCatalogueActivity; import eu.kanade.mangafeed.ui.activity.MangaCatalogueActivity;
import eu.kanade.mangafeed.ui.adapter.CatalogueHolder; import nucleus.presenter.RxPresenter;
import eu.kanade.mangafeed.view.CatalogueView;
import rx.Observable; import rx.Observable;
import rx.Subscription; import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers; import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers; import rx.schedulers.Schedulers;
import rx.subjects.PublishSubject; import rx.subjects.PublishSubject;
import timber.log.Timber; import timber.log.Timber;
import uk.co.ribot.easyadapter.EasyAdapter;
public class CataloguePresenter extends BasePresenter { public class CataloguePresenter extends RxPresenter<CatalogueActivity> {
CatalogueView view;
EasyAdapter<Manga> adapter;
Source selectedSource;
@Inject SourceManager sourceManager; @Inject SourceManager sourceManager;
@Inject DatabaseHelper db; @Inject DatabaseHelper db;
private Source selectedSource;
private String mSearchName; private String mSearchName;
private boolean mSearchMode; private boolean mSearchMode;
private final int SEARCH_TIMEOUT = 1000; private final int SEARCH_TIMEOUT = 1000;
private int mCurrentPage = 1;
private Subscription mMangaFetchSubscription; private Subscription mMangaFetchSubscription;
private Subscription mMangaSearchSubscription; private Subscription mMangaSearchSubscription;
@ -48,36 +47,43 @@ public class CataloguePresenter extends BasePresenter {
private PublishSubject<Observable<String>> mSearchViewPublishSubject; private PublishSubject<Observable<String>> mSearchViewPublishSubject;
private PublishSubject<Observable<List<Manga>>> mMangaDetailPublishSubject; private PublishSubject<Observable<List<Manga>>> mMangaDetailPublishSubject;
private final String CURRENT_PAGE = "CATALOGUE_CURRENT_PAGE";
public CataloguePresenter(CatalogueView view) { @Override
this.view = view; protected void onCreate(Bundle savedState) {
App.getComponent(view.getActivity()).inject(this); super.onCreate(savedState);
if (savedState != null) {
mCurrentPage = savedState.getInt(CURRENT_PAGE);
} }
public void initialize() { selectedSource = sourceManager.getSelectedSource();
initializeSource(); getMangasFromSource(mCurrentPage);
initializeAdapter();
initializeSearch(); initializeSearch();
initializeMangaDetailsLoader(); initializeMangaDetailsLoader();
}
@Override
protected void onTakeView(CatalogueActivity view) {
super.onTakeView(view);
view.setScrollPage(mCurrentPage - 1);
view.setToolbarTitle(selectedSource.getName());
if (view.getAdapter().getCount() == 0)
view.showProgressBar(); view.showProgressBar();
getMangasFromSource(1);
} }
private void initializeSource() { @Override
int sourceId = view.getIntent().getIntExtra(Intent.EXTRA_UID, -1); protected void onSave(@NonNull Bundle state) {
selectedSource = sourceManager.get(sourceId); super.onSave(state);
view.setTitle(selectedSource.getName()); state.putInt(CURRENT_PAGE, mCurrentPage);
}
private void initializeAdapter() {
adapter = new EasyAdapter<>(view.getActivity(), CatalogueHolder.class);
view.setAdapter(adapter);
view.setScrollListener();
view.setMangaClickListener();
} }
private void initializeSearch() { private void initializeSearch() {
remove(mSearchViewSubscription);
mSearchName = ""; mSearchName = "";
mSearchMode = false; mSearchMode = false;
mSearchViewPublishSubject = PublishSubject.create(); mSearchViewPublishSubject = PublishSubject.create();
@ -90,10 +96,12 @@ public class CataloguePresenter extends BasePresenter {
this::queryFromSearch, this::queryFromSearch,
error -> Timber.e(error.getCause(), error.getMessage())); error -> Timber.e(error.getCause(), error.getMessage()));
subscriptions.add(mSearchViewSubscription); add(mSearchViewSubscription);
} }
private void initializeMangaDetailsLoader() { private void initializeMangaDetailsLoader() {
remove(mMangaDetailFetchSubscription);
mMangaDetailPublishSubject = PublishSubject.create(); mMangaDetailPublishSubject = PublishSubject.create();
mMangaDetailFetchSubscription = Observable.switchOnNext(mMangaDetailPublishSubject) mMangaDetailFetchSubscription = Observable.switchOnNext(mMangaDetailPublishSubject)
@ -123,46 +131,39 @@ public class CataloguePresenter extends BasePresenter {
int index = getMangaIndex(manga); int index = getMangaIndex(manga);
// Get the image view associated with the manga. // Get the image view associated with the manga.
// If it's null (not visible in the screen) there's no need to update the image. // If it's null (not visible in the screen) there's no need to update the image.
ImageView imageView = view.getImageView(index); ImageView imageView = getView().getImageView(index);
if (imageView != null) { if (imageView != null) {
updateImage(imageView, manga.thumbnail_url); updateImage(imageView, manga.thumbnail_url);
} }
}); });
subscriptions.add(mMangaDetailFetchSubscription); add(mMangaDetailFetchSubscription);
} }
public void getMangasFromSource(int page) { public void getMangasFromSource(int page) {
subscriptions.remove(mMangaFetchSubscription);
mMangaFetchSubscription = getMangasSubscriber( mMangaFetchSubscription = getMangasSubscriber(
selectedSource.pullPopularMangasFromNetwork(page)); selectedSource.pullPopularMangasFromNetwork(page));
subscriptions.add(mMangaFetchSubscription);
} }
public void getMangasFromSearch(int page) { public void getMangasFromSearch(int page) {
subscriptions.remove(mMangaSearchSubscription);
mMangaSearchSubscription = getMangasSubscriber( mMangaSearchSubscription = getMangasSubscriber(
selectedSource.searchMangasFromNetwork(mSearchName, page)); selectedSource.searchMangasFromNetwork(mSearchName, page));
subscriptions.add(mMangaSearchSubscription);
} }
private Subscription getMangasSubscriber(Observable<List<Manga>> mangas) { private Subscription getMangasSubscriber(Observable<List<Manga>> mangas) {
return mangas return mangas
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.flatMap(Observable::from) .flatMap(Observable::from)
.map(this::networkToLocalManga) .map(this::networkToLocalManga)
.toList() .toList()
.subscribe(newMangas -> { .observeOn(AndroidSchedulers.mainThread())
.compose(deliverReplay())
.subscribe(this.split((view, newMangas) -> {
view.hideProgressBar(); view.hideProgressBar();
adapter.addItems(newMangas); view.onMangasNext(newMangas);
if (mMangaDetailPublishSubject != null) if (mMangaDetailPublishSubject != null)
mMangaDetailPublishSubject.onNext(Observable.just(newMangas)); mMangaDetailPublishSubject.onNext(Observable.just(newMangas));
}); }));
} }
private Manga networkToLocalManga(Manga networkManga) { private Manga networkToLocalManga(Manga networkManga) {
@ -175,10 +176,10 @@ public class CataloguePresenter extends BasePresenter {
} }
public void onMangaClick(int position) { public void onMangaClick(int position) {
Intent intent = new Intent(view.getActivity(), MangaCatalogueActivity.class); Intent intent = new Intent(getView().getActivity(), MangaCatalogueActivity.class);
Manga selectedManga = adapter.getItem(position); Manga selectedManga = getView().getAdapter().getItem(position);
EventBus.getDefault().postSticky(selectedManga); EventBus.getDefault().postSticky(selectedManga);
view.getActivity().startActivity(intent); getView().getActivity().startActivity(intent);
} }
public void onQueryTextChange(String query) { public void onQueryTextChange(String query) {
@ -201,26 +202,27 @@ public class CataloguePresenter extends BasePresenter {
} }
mSearchName = query; mSearchName = query;
adapter.getItems().clear(); getView().getAdapter().getItems().clear();
view.showProgressBar(); getView().showProgressBar();
view.resetScrollListener(); getView().resetScrollListener();
loadMoreMangas(1); loadMoreMangas(1);
} }
public void loadMoreMangas(int page) { public void loadMoreMangas(int page) {
if (page > 1) { if (page > 1) {
view.showGridProgressBar(); getView().showGridProgressBar();
} }
if (mSearchMode) { if (mSearchMode) {
getMangasFromSearch(page); getMangasFromSearch(page);
} else { } else {
getMangasFromSource(page); getMangasFromSource(page);
} }
mCurrentPage = page;
} }
private int getMangaIndex(Manga manga) { private int getMangaIndex(Manga manga) {
for (int i = 0; i < adapter.getCount(); i++) { for (int i = 0; i < getView().getAdapter().getCount(); i++) {
if (manga.id == adapter.getItem(i).id) { if (manga.id == getView().getAdapter().getItem(i).id) {
return i; return i;
} }
} }
@ -228,7 +230,7 @@ public class CataloguePresenter extends BasePresenter {
} }
private void updateImage(ImageView imageView, String thumbnail) { private void updateImage(ImageView imageView, String thumbnail) {
Glide.with(view.getActivity()) Glide.with(getView().getActivity())
.load(thumbnail) .load(thumbnail)
.centerCrop() .centerCrop()
.into(imageView); .into(imageView);

View file

@ -0,0 +1,42 @@
package eu.kanade.mangafeed.ui.activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import eu.kanade.mangafeed.App;
import eu.kanade.mangafeed.AppComponent;
import nucleus.factory.PresenterFactory;
import nucleus.presenter.Presenter;
import nucleus.view.NucleusAppCompatActivity;
public class BaseActivity2<P extends Presenter> extends NucleusAppCompatActivity<P> {
@Override
protected void onCreate(Bundle savedInstanceState) {
final PresenterFactory<P> superFactory = super.getPresenterFactory();
setPresenterFactory(() -> {
P presenter = superFactory.createPresenter();
App.getComponentReflection(getActivity()).inject(presenter);
return presenter;
});
super.onCreate(savedInstanceState);
}
protected void setupToolbar(Toolbar toolbar) {
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
public void setToolbarTitle(String title) {
getSupportActionBar().setTitle(title);
}
protected AppComponent applicationComponent() {
return App.get(this).getComponent();
}
public Context getActivity() {
return this;
}
}

View file

@ -9,15 +9,20 @@ import android.widget.GridView;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import java.util.List;
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import eu.kanade.mangafeed.R; import eu.kanade.mangafeed.R;
import eu.kanade.mangafeed.data.models.Manga;
import eu.kanade.mangafeed.presenter.CataloguePresenter; import eu.kanade.mangafeed.presenter.CataloguePresenter;
import eu.kanade.mangafeed.view.CatalogueView; import eu.kanade.mangafeed.ui.adapter.CatalogueHolder;
import eu.kanade.mangafeed.widget.EndlessScrollListener; import eu.kanade.mangafeed.widget.EndlessScrollListener;
import nucleus.factory.RequiresPresenter;
import uk.co.ribot.easyadapter.EasyAdapter; import uk.co.ribot.easyadapter.EasyAdapter;
public class CatalogueActivity extends BaseActivity implements CatalogueView { @RequiresPresenter(CataloguePresenter.class)
public class CatalogueActivity extends BaseActivity2<CataloguePresenter> {
@Bind(R.id.toolbar) @Bind(R.id.toolbar)
Toolbar toolbar; Toolbar toolbar;
@ -31,8 +36,7 @@ public class CatalogueActivity extends BaseActivity implements CatalogueView {
@Bind(R.id.progress_grid) @Bind(R.id.progress_grid)
ProgressBar progress_grid; ProgressBar progress_grid;
private CataloguePresenter presenter; private EasyAdapter<Manga> adapter;
private EndlessScrollListener scroll_listener; private EndlessScrollListener scroll_listener;
@Override @Override
@ -43,14 +47,9 @@ public class CatalogueActivity extends BaseActivity implements CatalogueView {
setupToolbar(toolbar); setupToolbar(toolbar);
presenter = new CataloguePresenter(this); initializeAdapter();
presenter.initialize(); initializeClickListener();
} initializeScrollListener();
@Override
public void onDestroy() {
super.onDestroy();
presenter.destroySubscriptions();
} }
@Override @Override
@ -65,44 +64,39 @@ public class CatalogueActivity extends BaseActivity implements CatalogueView {
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override @Override
public boolean onQueryTextSubmit(String query) { public boolean onQueryTextSubmit(String query) {
presenter.onQueryTextChange(query); getPresenter().onQueryTextChange(query);
return true; return true;
} }
@Override @Override
public boolean onQueryTextChange(String newText) { public boolean onQueryTextChange(String newText) {
presenter.onQueryTextChange(newText); getPresenter().onQueryTextChange(newText);
return true; return true;
} }
}); });
} }
// CatalogueView public EasyAdapter<Manga> getAdapter() {
return adapter;
@Override
public void setTitle(String title) {
setToolbarTitle(title);
} }
@Override public void initializeAdapter() {
public void setAdapter(EasyAdapter adapter) { adapter = new EasyAdapter<>(this, CatalogueHolder.class);
manga_list.setAdapter(adapter); manga_list.setAdapter(adapter);
} }
@Override public void initializeClickListener() {
public void setMangaClickListener() {
manga_list.setOnItemClickListener( manga_list.setOnItemClickListener(
(parent, view, position, id) -> (parent, view, position, id) ->
presenter.onMangaClick(position) getPresenter().onMangaClick(position)
); );
} }
@Override public void initializeScrollListener() {
public void setScrollListener() {
scroll_listener = new EndlessScrollListener() { scroll_listener = new EndlessScrollListener() {
@Override @Override
public boolean onLoadMore(int page, int totalItemsCount) { public boolean onLoadMore(int page, int totalItemsCount) {
presenter.loadMoreMangas(page); getPresenter().loadMoreMangas(page);
return true; return true;
} }
}; };
@ -110,28 +104,31 @@ public class CatalogueActivity extends BaseActivity implements CatalogueView {
manga_list.setOnScrollListener(scroll_listener); manga_list.setOnScrollListener(scroll_listener);
} }
@Override
public void resetScrollListener() { public void resetScrollListener() {
scroll_listener.resetScroll(); scroll_listener.resetScroll();
} }
@Override public int getScrollPage() {
return scroll_listener.getCurrentPage();
}
public void setScrollPage(int page) {
scroll_listener.setCurrentPage(page);
}
public void showProgressBar() { public void showProgressBar() {
progress.setVisibility(ProgressBar.VISIBLE); progress.setVisibility(ProgressBar.VISIBLE);
} }
@Override
public void showGridProgressBar() { public void showGridProgressBar() {
progress_grid.setVisibility(ProgressBar.VISIBLE); progress_grid.setVisibility(ProgressBar.VISIBLE);
} }
@Override
public void hideProgressBar() { public void hideProgressBar() {
progress.setVisibility(ProgressBar.GONE); progress.setVisibility(ProgressBar.GONE);
progress_grid.setVisibility(ProgressBar.GONE); progress_grid.setVisibility(ProgressBar.GONE);
} }
@Override
public ImageView getImageView(int position) { public ImageView getImageView(int position) {
View v = manga_list.getChildAt(position - View v = manga_list.getChildAt(position -
manga_list.getFirstVisiblePosition()); manga_list.getFirstVisiblePosition());
@ -141,4 +138,8 @@ public class CatalogueActivity extends BaseActivity implements CatalogueView {
return (ImageView) v.findViewById(R.id.catalogue_thumbnail); return (ImageView) v.findViewById(R.id.catalogue_thumbnail);
} }
public void onMangasNext(List<Manga> newMangas) {
adapter.addItems(newMangas);
}
} }

View file

@ -72,4 +72,12 @@ public abstract class EndlessScrollListener implements AbsListView.OnScrollListe
public void onScrollStateChanged(AbsListView view, int scrollState) { public void onScrollStateChanged(AbsListView view, int scrollState) {
// Don't take any action on changed // Don't take any action on changed
} }
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
} }