diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..6560a98
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 0000000..797acea
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 2ef7967..8bded9c 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -238,6 +238,8 @@ dependencies {
exclude group: 'org.slf4j'
exclude group: 'xmlpull'
}
+
+ implementation 'com.nshmura:recyclertablayout:1.5.0'
}
greendao {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 64f9cdd..4a886b7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -118,6 +118,7 @@
+
diff --git a/app/src/main/java/xyz/fycz/myreader/base/BaseActivity.java b/app/src/main/java/xyz/fycz/myreader/base/BaseActivity.java
index 88876d0..34def62 100644
--- a/app/src/main/java/xyz/fycz/myreader/base/BaseActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/base/BaseActivity.java
@@ -47,7 +47,7 @@ public abstract class BaseActivity extends SwipeBackActivity {
protected abstract void bindView();
/************************init area************************************/
- protected void addDisposable(Disposable d) {
+ public void addDisposable(Disposable d) {
if (mDisposable == null) {
mDisposable = new CompositeDisposable();
}
diff --git a/app/src/main/java/xyz/fycz/myreader/base/LazyFragment.kt b/app/src/main/java/xyz/fycz/myreader/base/LazyFragment.kt
new file mode 100644
index 0000000..6af8dfa
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/base/LazyFragment.kt
@@ -0,0 +1,86 @@
+package xyz.fycz.myreader.base
+
+import androidx.fragment.app.Fragment
+import io.reactivex.disposables.CompositeDisposable
+import io.reactivex.disposables.Disposable
+
+/**
+ * @author fengyue
+ * @date 2021/7/22 11:46
+ */
+abstract class LazyFragment : Fragment() {
+ protected var mDisposable: CompositeDisposable? = null
+ /**
+ * 是否执行懒加载
+ */
+ private var isLoaded = false
+
+ /**
+ * 当前Fragment是否对用户可见
+ */
+ private var isVisibleToUser = false
+
+ /**
+ * 当使用ViewPager+Fragment形式会调用该方法时,setUserVisibleHint会优先Fragment生命周期函数调用,
+ * 所以这个时候就,会导致在setUserVisibleHint方法执行时就执行了懒加载,
+ * 而不是在onResume方法实际调用的时候执行懒加载。所以需要这个变量
+ */
+ private var isCallResume = false
+
+ /**
+ * 是否调用了setUserVisibleHint方法。处理show+add+hide模式下,默认可见 Fragment 不调用
+ * onHiddenChanged 方法,进而不执行懒加载方法的问题。
+ */
+ private var isCallUserVisibleHint = false
+
+ protected open fun addDisposable(d: Disposable?) {
+ if (mDisposable == null) {
+ mDisposable = CompositeDisposable()
+ }
+ mDisposable!!.add(d!!)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ isCallResume = true
+ if (!isCallUserVisibleHint) isVisibleToUser = !isHidden
+ judgeLazyInit()
+ }
+
+
+ private fun judgeLazyInit() {
+ if (!isLoaded && isVisibleToUser && isCallResume) {
+ lazyInit()
+ isLoaded = true
+ }
+ }
+
+ override fun onHiddenChanged(hidden: Boolean) {
+ super.onHiddenChanged(hidden)
+ isVisibleToUser = !hidden
+ judgeLazyInit()
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ isLoaded = false
+ isVisibleToUser = false
+ isCallUserVisibleHint = false
+ isCallResume = false
+ }
+
+ override fun setUserVisibleHint(isVisibleToUser: Boolean) {
+ super.setUserVisibleHint(isVisibleToUser)
+ this.isVisibleToUser = isVisibleToUser
+ isCallUserVisibleHint = true
+ judgeLazyInit()
+ }
+
+ override fun onDetach() {
+ super.onDetach()
+ if (mDisposable != null) {
+ mDisposable!!.clear()
+ }
+ }
+ abstract fun lazyInit()
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/FindKind.java b/app/src/main/java/xyz/fycz/myreader/entity/FindKind.java
new file mode 100644
index 0000000..03b2797
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/entity/FindKind.java
@@ -0,0 +1,45 @@
+package xyz.fycz.myreader.entity;
+
+/**
+ * @author fengyue
+ * @date 2021/7/21 20:44
+ */
+public class FindKind {
+ private String tag;
+ private String name;
+ private String url;
+ private int maxPage;
+
+ public String getTag() {
+ return tag;
+ }
+
+ public void setTag(String tag) {
+ this.tag = tag;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public int getMaxPage() {
+ return maxPage;
+ }
+
+ public void setMaxPage(int maxPage) {
+ this.maxPage = maxPage;
+ }
+}
+
diff --git a/app/src/main/java/xyz/fycz/myreader/entity/StrResponse.java b/app/src/main/java/xyz/fycz/myreader/entity/StrResponse.java
index 9ecec56..dad38bd 100644
--- a/app/src/main/java/xyz/fycz/myreader/entity/StrResponse.java
+++ b/app/src/main/java/xyz/fycz/myreader/entity/StrResponse.java
@@ -46,38 +46,42 @@ public class StrResponse {
public String body() {
if (body == null) {
- ResponseBody body = response.body();
- if (body != null) {
- try {
- byte[] responseBytes = UTF8BOMFighter.removeUTF8BOM(body.bytes());
- if (!TextUtils.isEmpty(encodeType)) {
- try {
- this.body = new String((responseBytes), Charset.forName(encodeType));
- Log.d("Http: read finish", this.body);
- return this.body;
- } catch (Exception ignored) {
+ if (response != null) {
+ ResponseBody body = response.body();
+ if (body != null) {
+ try {
+ byte[] responseBytes = UTF8BOMFighter.removeUTF8BOM(body.bytes());
+ if (!TextUtils.isEmpty(encodeType)) {
+ try {
+ this.body = new String((responseBytes), Charset.forName(encodeType));
+ Log.d("Http: read finish", this.body);
+ return this.body;
+ } catch (Exception ignored) {
+ }
}
- }
- String charsetStr;
- MediaType mediaType = body.contentType();
- //根据http头判断
- if (mediaType != null) {
- Charset charset = mediaType.charset();
- if (charset != null) {
- this.body = new String((responseBytes), charset);
- Log.d("Http: read finish", this.body);
- return this.body;
+ String charsetStr;
+ MediaType mediaType = body.contentType();
+ //根据http头判断
+ if (mediaType != null) {
+ Charset charset = mediaType.charset();
+ if (charset != null) {
+ this.body = new String((responseBytes), charset);
+ Log.d("Http: read finish", this.body);
+ return this.body;
+ }
}
+ //根据内容判断
+ charsetStr = EncodingDetect.getEncodeInHtml(responseBytes);
+ this.body = new String(responseBytes, Charset.forName(charsetStr));
+ Log.d("Http: read finish", this.body);
+ return this.body;
+ } catch (IOException e) {
+ e.printStackTrace();
+ this.body = "";
}
- //根据内容判断
- charsetStr = EncodingDetect.getEncodeInHtml(responseBytes);
- this.body = new String(responseBytes, Charset.forName(charsetStr));
- Log.d("Http: read finish", this.body);
- return this.body;
- } catch (IOException e) {
- e.printStackTrace();
- this.body = "";
}
+ } else {
+ this.body = "";
}
}
return this.body;
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java
index 0b191e5..b3ec45a 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/AboutActivity.java
@@ -86,7 +86,7 @@ public class AboutActivity extends BaseActivity {
binding.il.rlOfficialWeb.setOnClickListener(v -> {
MyAlertDialog.showFullWebViewDia(this, URLCONST.OFFICIAL_WEB,
- true, null);
+ true, null);
});
binding.il.rlGit.setOnClickListener(v -> {
MyAlertDialog.showFullWebViewDia(this, getString(R.string.this_github_url),
@@ -153,6 +153,7 @@ public class AboutActivity extends BaseActivity {
@Override
public void onSubscribe(Disposable d) {
disposable[0] = d;
+ addDisposable(d);
}
@Override
@@ -191,6 +192,11 @@ public class AboutActivity extends BaseActivity {
}
emitter.onComplete();
}).compose(RxUtils::toSimpleSingle).subscribe(new MyObserver() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
+
@Override
public void onNext(@NotNull File file) {
ShareUtils.share(AboutActivity.this, file, "分享日志文件", "application/x-zip-compressed");
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/AdSettingActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/AdSettingActivity.java
index 3f416d0..733270d 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/activity/AdSettingActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/AdSettingActivity.java
@@ -77,6 +77,7 @@ public class AdSettingActivity extends BaseActivity {
@Override
public void onSubscribe(Disposable d) {
cancelDis = d;
+ addDisposable(d);
}
@Override
@@ -116,6 +117,7 @@ public class AdSettingActivity extends BaseActivity {
@Override
public void onSubscribe(Disposable d) {
cancelDis = d;
+ addDisposable(d);
}
@Override
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java
index 920908c..cacc830 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java
@@ -372,6 +372,11 @@ public class BookDetailedActivity extends BaseActivity {
binding.pbLoading.setVisibility(View.VISIBLE);
BookInfoCrawler bic = (BookInfoCrawler) rc;
BookApi.getBookInfo(mBook, bic).compose(RxUtils::toSimpleSingle).subscribe(new MyObserver() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
+
@Override
public void onNext(@NotNull Book book) {
if (!App.isDestroy(BookDetailedActivity.this)) {
@@ -438,6 +443,7 @@ public class BookDetailedActivity extends BaseActivity {
@Override
public void onSubscribe(Disposable d) {
chaptersDis = d;
+ addDisposable(d);
}
@Override
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/BookstoreActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/BookstoreActivity.java
index 9e75a69..03e41c4 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/activity/BookstoreActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/BookstoreActivity.java
@@ -36,7 +36,7 @@ import xyz.fycz.myreader.util.SharedPreUtils;
import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.webapi.BookStoreApi;
import xyz.fycz.myreader.webapi.ResultCallback;
-import xyz.fycz.myreader.webapi.crawler.base.FindCrawler;
+import xyz.fycz.myreader.webapi.crawler.base.FindCrawler3;
import xyz.fycz.myreader.webapi.crawler.find.QiDianMobileRank;
/**
@@ -46,7 +46,7 @@ import xyz.fycz.myreader.webapi.crawler.find.QiDianMobileRank;
public class BookstoreActivity extends BaseActivity {
private ActiityBookstoreBinding binding;
- private FindCrawler findCrawler;
+ private FindCrawler3 findCrawler3;
private LinearLayoutManager mLinearLayoutManager;
private BookStoreBookTypeAdapter mBookStoreBookTypeAdapter;
private List mBookTypes;
@@ -107,8 +107,8 @@ public class BookstoreActivity extends BaseActivity {
super.setUpToolbar(toolbar);
setStatusBarColor(R.color.colorPrimary, true);
String subTitle = "";
- if (findCrawler != null) {
- String name = findCrawler.getFindName();
+ if (findCrawler3 != null) {
+ String name = findCrawler3.getFindName();
title = name.substring(0, name.indexOf("["));
subTitle = name.substring(name.indexOf("[") + 1, name.length() - 1);
}
@@ -119,7 +119,7 @@ public class BookstoreActivity extends BaseActivity {
@Override
protected void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
- findCrawler = (FindCrawler) getIntent().getSerializableExtra(APPCONST.FIND_CRAWLER);
+ findCrawler3 = (FindCrawler3) getIntent().getSerializableExtra(APPCONST.FIND_CRAWLER);
}
@Override
@@ -139,7 +139,7 @@ public class BookstoreActivity extends BaseActivity {
getBooksData();
});
- mBookStoreBookAdapter = new BookStoreBookAdapter(findCrawler.hasImg(), this);
+ mBookStoreBookAdapter = new BookStoreBookAdapter(findCrawler3.hasImg(), this);
binding.rvBookList.setLayoutManager(new LinearLayoutManager(this));
binding.rvBookList.setAdapter(mBookStoreBookAdapter);
binding.refreshLayout.setOnReloadingListener(this::getData);
@@ -150,7 +150,7 @@ public class BookstoreActivity extends BaseActivity {
super.initClick();
mBookStoreBookAdapter.setOnItemClickListener((view, pos) -> {
Book book = bookList.get(pos);
- if (!findCrawler.needSearch()) {
+ if (!findCrawler3.needSearch()) {
goToBookDetail(book);
} else {
if (BookService.getInstance().isBookCollected(book)) {
@@ -174,7 +174,7 @@ public class BookstoreActivity extends BaseActivity {
protected void processLogic() {
super.processLogic();
getData();
- if (findCrawler.needSearch()) {
+ if (findCrawler3.needSearch()) {
SharedPreUtils spu = SharedPreUtils.getInstance();
boolean isReadTopTip = spu.getBoolean(getString(R.string.isReadTopTip), false);
if (!isReadTopTip) {
@@ -189,15 +189,15 @@ public class BookstoreActivity extends BaseActivity {
* 获取页面数据
*/
private void getData() {
- if (findCrawler instanceof QiDianMobileRank) {
+ if (findCrawler3 instanceof QiDianMobileRank) {
SharedPreUtils spu = SharedPreUtils.getInstance();
if (spu.getString(getString(R.string.qdCookie), "").equals("")) {
- ((QiDianMobileRank) findCrawler).initCookie(this, new ResultCallback() {
+ ((QiDianMobileRank) findCrawler3).initCookie(this, new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
if (App.isDestroy(BookstoreActivity.this)) return;
spu.putString(getString(R.string.qdCookie), (String) o);
- mBookTypes = findCrawler.getBookTypes();
+ mBookTypes = findCrawler3.getBookTypes();
initBooks();
}
@@ -209,13 +209,13 @@ public class BookstoreActivity extends BaseActivity {
}
});
} else {
- mBookTypes = findCrawler.getBookTypes();
+ mBookTypes = findCrawler3.getBookTypes();
initBooks();
}
- } else if ((mBookTypes = findCrawler.getBookTypes()) != null) {
+ } else if ((mBookTypes = findCrawler3.getBookTypes()) != null) {
initBooks();
} else {
- BookStoreApi.getBookTypeList(findCrawler, new ResultCallback() {
+ BookStoreApi.getBookTypeList(findCrawler3, new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
if (App.isDestroy(BookstoreActivity.this)) return;
@@ -244,14 +244,14 @@ public class BookstoreActivity extends BaseActivity {
* 获取小数列表数据
*/
private void getBooksData() {
- if (findCrawler.getTypePage(curType, page)) {
+ if (findCrawler3.getTypePage(curType, page)) {
binding.srlBookList.finishLoadMoreWithNoMoreData();
return;
}
mHandler.sendEmptyMessage(3);
- if (findCrawler instanceof QiDianMobileRank) {
- ((QiDianMobileRank) findCrawler).getRankBooks(curType, new ResultCallback() {
+ if (findCrawler3 instanceof QiDianMobileRank) {
+ ((QiDianMobileRank) findCrawler3).getRankBooks(curType, new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
if (App.isDestroy(BookstoreActivity.this)) return;
@@ -287,7 +287,7 @@ public class BookstoreActivity extends BaseActivity {
}
});
} else {
- BookStoreApi.getBookRankList(curType, findCrawler, new ResultCallback() {
+ BookStoreApi.getBookRankList(curType, findCrawler3, new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
if (App.isDestroy(BookstoreActivity.this)) return;
@@ -381,7 +381,7 @@ public class BookstoreActivity extends BaseActivity {
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
- if (findCrawler.needSearch()) {
+ if (findCrawler3.needSearch()) {
menu.findItem(R.id.action_tip).setVisible(true);
}
return true;
@@ -395,14 +395,9 @@ public class BookstoreActivity extends BaseActivity {
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.action_tip:
- mHandler.sendEmptyMessage(6);
- return true;
- case R.id.action_refresh:
- binding.refreshLayout.showLoading();
- getData();
- return true;
+ if (item.getItemId() == R.id.action_tip) {
+ mHandler.sendEmptyMessage(6);
+ return true;
}
return false;
}
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/FindBookActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/FindBookActivity.java
new file mode 100644
index 0000000..f902bea
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/FindBookActivity.java
@@ -0,0 +1,162 @@
+package xyz.fycz.myreader.ui.activity;
+
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+
+import androidx.appcompat.widget.Toolbar;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentPagerAdapter;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import io.reactivex.disposables.Disposable;
+import xyz.fycz.myreader.R;
+import xyz.fycz.myreader.base.BaseActivity;
+import xyz.fycz.myreader.base.BitIntentDataManager;
+import xyz.fycz.myreader.base.observer.MyObserver;
+import xyz.fycz.myreader.databinding.ActivityFindBookBinding;
+import xyz.fycz.myreader.greendao.entity.rule.BookSource;
+import xyz.fycz.myreader.ui.adapter.TabFragmentPageAdapter;
+import xyz.fycz.myreader.ui.dialog.DialogCreator;
+import xyz.fycz.myreader.ui.fragment.FindBook1Fragment;
+import xyz.fycz.myreader.util.ToastUtils;
+import xyz.fycz.myreader.util.utils.RxUtils;
+import xyz.fycz.myreader.webapi.crawler.base.FindCrawler;
+import xyz.fycz.myreader.webapi.crawler.find.QiDianFindCrawler;
+import xyz.fycz.myreader.webapi.crawler.source.find.ThirdFindCrawler;
+
+/**
+ * @author fengyue
+ * @date 2021/7/21 20:10
+ */
+public class FindBookActivity extends BaseActivity {
+ private ActivityFindBookBinding binding;
+ private BookSource source;
+ private FindCrawler findCrawler;
+ private List groups;
+
+ @Override
+ protected void bindView() {
+ binding = ActivityFindBookBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
+ }
+
+ @Override
+ protected void initData(Bundle savedInstanceState) {
+ super.initData(savedInstanceState);
+ Object obj = BitIntentDataManager.getInstance().getData(getIntent());
+ if (obj instanceof BookSource) {
+ source = (BookSource) obj;
+ findCrawler = new ThirdFindCrawler(source);
+ } else if (obj instanceof FindCrawler) {
+ findCrawler = (FindCrawler) obj;
+ }
+ if (findCrawler == null) {
+ finish();
+ return;
+ }
+ initData();
+ }
+
+ @Override
+ protected void initWidget() {
+ binding.loading.setOnReloadingListener(this::initData);
+ }
+
+ private void initData() {
+ findCrawler.initData()
+ .compose(RxUtils::toSimpleSingle)
+ .subscribe(new MyObserver() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
+
+ @Override
+ public void onNext(@NotNull Boolean aBoolean) {
+ if (aBoolean) {
+ groups = findCrawler.getGroups();
+ setUpToolbar();
+ initFragments();
+ } else {
+ ToastUtils.showError("发现规则语法错误");
+ }
+ binding.loading.showFinish();
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ e.printStackTrace();
+ ToastUtils.showError("数据加载失败\n" + e.getLocalizedMessage());
+ binding.loading.showError();
+ }
+ });
+ }
+
+ @Override
+ protected void setUpToolbar(Toolbar toolbar) {
+ super.setUpToolbar(toolbar);
+ setStatusBarColor(R.color.colorPrimary, true);
+ }
+
+ private void setUpToolbar() {
+ if (groups.size() == 1) {
+ binding.tabTlIndicator.setVisibility(View.GONE);
+ getSupportActionBar().setTitle(groups.get(0));
+ } else {
+ binding.tabTlIndicator.setVisibility(View.VISIBLE);
+ }
+ }
+
+ private void initFragments() {
+ TabFragmentPageAdapter adapter = new TabFragmentPageAdapter(getSupportFragmentManager());
+ for (String group : groups) {
+ adapter.addFragment(new FindBook1Fragment(findCrawler.getKindsByKey(group), findCrawler), group);
+ }
+ binding.tabVp.setAdapter(adapter);
+ binding.tabVp.setOffscreenPageLimit(3);
+ binding.tabTlIndicator.setUpWithViewPager(binding.tabVp);
+ }
+/********************************Event***************************************/
+ /**
+ * 创建菜单
+ *
+ * @param menu
+ * @return
+ */
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_store, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ if (findCrawler.needSearch()) {
+ menu.findItem(R.id.action_tip).setVisible(true);
+ }
+ return true;
+ }
+
+ /**
+ * 导航栏菜单点击事件
+ *
+ * @param item
+ * @return
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == R.id.action_tip) {
+ DialogCreator.createTipDialog(this,
+ getResources().getString(R.string.top_sort_tip, "此发现"));
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/QRCodeScanActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/QRCodeScanActivity.java
index a334286..4cf585e 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/activity/QRCodeScanActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/QRCodeScanActivity.java
@@ -21,6 +21,7 @@ import java.util.List;
import cn.bingoogolapple.qrcode.core.QRCodeView;
import io.reactivex.Single;
import io.reactivex.SingleOnSubscribe;
+import io.reactivex.disposables.Disposable;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.base.BaseActivity;
import xyz.fycz.myreader.base.observer.MySingleObserver;
@@ -210,6 +211,10 @@ public class QRCodeScanActivity extends BaseActivity implements QRCodeView.Deleg
emitter.onSuccess(bitmap);
}).compose(RxUtils::toSimpleSingle)
.subscribe(new MySingleObserver() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
@Override
public void onSuccess(Bitmap bitmap) {
binding.zxingview.decodeQRCode(bitmap);
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java
index 8b3b0bc..5b854d8 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java
@@ -51,6 +51,7 @@ import java.util.List;
import java.util.Locale;
import io.reactivex.Single;
+import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import xyz.fycz.myreader.ActivityManage;
import xyz.fycz.myreader.R;
@@ -1576,6 +1577,10 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
BookApi.getChapterContent(chapter, mBook, mReadCrawler)
.subscribeOn(Schedulers.from(App.getApplication().getmFixedThreadPool()))
.subscribe(new MyObserver() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
@Override
public void onNext(@NotNull String s) {
downloadingChapter = chapter.getTitle();
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadRecordActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadRecordActivity.java
index f87e7e9..56f45b1 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadRecordActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReadRecordActivity.java
@@ -15,6 +15,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
+import io.reactivex.disposables.Disposable;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.base.BaseActivity;
import xyz.fycz.myreader.base.BitIntentDataManager;
@@ -67,6 +68,10 @@ public class ReadRecordActivity extends BaseActivity {
recordService = ReadRecordService.getInstance();
recordService.getAllRecordsByTime().compose(RxUtils::toSimpleSingle)
.subscribe(new MySingleObserver>() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
@Override
public void onSuccess(@NotNull List readRecords) {
records = readRecords;
@@ -165,6 +170,10 @@ public class ReadRecordActivity extends BaseActivity {
case 0:
recordService.removeAll().compose(RxUtils::toSimpleSingle)
.subscribe(new MySingleObserver() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
@Override
public void onSuccess(@NotNull Boolean aBoolean) {
ToastUtils.showSuccess("阅读记录已全部移除");
@@ -183,6 +192,10 @@ public class ReadRecordActivity extends BaseActivity {
case 1:
recordService.removeAllTime(records).compose(RxUtils::toSimpleSingle)
.subscribe(new MySingleObserver() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
@Override
public void onSuccess(@NotNull Boolean aBoolean) {
ToastUtils.showSuccess("阅读时长已全部清空");
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReplaceRuleActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReplaceRuleActivity.java
index ca36276..98b34cd 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/activity/ReplaceRuleActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/ReplaceRuleActivity.java
@@ -29,6 +29,7 @@ import io.reactivex.Observable;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
+import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.base.BaseActivity;
@@ -76,6 +77,10 @@ public class ReplaceRuleActivity extends BaseActivity {
protected void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState);
ReplaceRuleManager.getAll().subscribe(new MySingleObserver>() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
@Override
public void onSuccess(@NonNull List replaceRuleBeans) {
mReplaceRules = replaceRuleBeans;
@@ -303,6 +308,10 @@ public class ReplaceRuleActivity extends BaseActivity {
Observable observable = ReplaceRuleManager.importReplaceRule(text);
if (observable != null) {
observable.subscribe(new MyObserver() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
@Override
public void onNext(Boolean aBoolean) {
if (aBoolean) {
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java
index 91ef2e6..683acb1 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/SearchBookActivity.java
@@ -368,6 +368,10 @@ public class SearchBookActivity extends BaseActivity {
mSourcesName, isDisables, dSourceCount, (dialog, which) -> {
BookSourceManager.saveDatas(sources)
.subscribe(new MySingleObserver() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
@Override
public void onSuccess(@NonNull Boolean aBoolean) {
if (aBoolean) {
@@ -408,6 +412,10 @@ public class SearchBookActivity extends BaseActivity {
headers.put("Cookie", cookie);
emitter.onSuccess(parseHotKeys(OkHttpUtils.getHtml(url, null, "utf-8", headers)));
}).compose(RxUtils::toSimpleSingle).subscribe(new MySingleObserver() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
@Override
public void onSuccess(@NotNull Boolean b) {
initSuggestionList();
@@ -448,6 +456,7 @@ public class SearchBookActivity extends BaseActivity {
@Override
public void onSubscribe(Disposable d) {
sugDis = d;
+ addDisposable(d);
}
@Override
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/SourceDebugActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/SourceDebugActivity.java
index cead3f2..b3bc7b0 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/activity/SourceDebugActivity.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/SourceDebugActivity.java
@@ -190,6 +190,7 @@ public class SourceDebugActivity extends BaseActivity {
@Override
public void onSubscribe(Disposable d) {
disposable = d;
+ addDisposable(d);
}
@Override
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/FindBookHolder.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/FindBookHolder.java
new file mode 100644
index 0000000..e8e7567
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/FindBookHolder.java
@@ -0,0 +1,154 @@
+package xyz.fycz.myreader.ui.adapter.holder;
+
+import android.app.Activity;
+import android.util.Log;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.zhy.view.flowlayout.TagFlowLayout;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import xyz.fycz.myreader.R;
+import xyz.fycz.myreader.application.App;
+import xyz.fycz.myreader.base.adapter.ViewHolderImpl;
+import xyz.fycz.myreader.base.observer.MyObserver;
+import xyz.fycz.myreader.entity.SearchBookBean;
+import xyz.fycz.myreader.greendao.entity.Book;
+import xyz.fycz.myreader.greendao.entity.rule.BookSource;
+import xyz.fycz.myreader.model.sourceAnalyzer.BookSourceManager;
+import xyz.fycz.myreader.ui.adapter.BookTagAdapter;
+import xyz.fycz.myreader.util.help.StringHelper;
+import xyz.fycz.myreader.util.utils.KeyWordUtils;
+import xyz.fycz.myreader.util.utils.NetworkUtils;
+import xyz.fycz.myreader.util.utils.RxUtils;
+import xyz.fycz.myreader.webapi.BookApi;
+import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil;
+import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler;
+import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler;
+import xyz.fycz.myreader.widget.CoverImageView;
+
+/**
+ * @author fengyue
+ * @date 2021/7/22 9:34
+ */
+public class FindBookHolder extends ViewHolderImpl {
+ private List tagList = new ArrayList<>();
+
+ private CoverImageView ivBookImg;
+ private TextView tvBookName;
+ private TagFlowLayout tflBookTag;
+ private TextView tvDesc;
+ private TextView tvAuthor;
+ private TextView tvSource;
+ private TextView tvNewestChapter;
+
+ @Override
+ protected int getItemLayoutId() {
+ return R.layout.listview_search_book_item;
+ }
+
+ @Override
+ public void initView() {
+ ivBookImg = findById(R.id.iv_book_img);
+ tvBookName = findById(R.id.tv_book_name);
+ tflBookTag = findById(R.id.tfl_book_tag);
+ tvAuthor = findById(R.id.tv_book_author);
+ tvDesc = findById(R.id.tv_book_desc);
+ tvSource = findById(R.id.tv_book_source);
+ tvNewestChapter = findById(R.id.tv_book_newest_chapter);
+ getItemView().setBackgroundColor(getContext().getResources().getColor(R.color.colorForeground));
+ }
+
+ @Override
+ public void onBind(RecyclerView.ViewHolder holder, Book data, int pos) {
+ BookSource source = BookSourceManager.getBookSourceByStr(data.getSource());
+ ReadCrawler rc = ReadCrawlerUtil.getReadCrawler(source);
+ if (StringHelper.isEmpty(data.getImgUrl())) {
+ data.setImgUrl("");
+ }
+ if (!App.isDestroy((Activity) getContext())) {
+ ivBookImg.load(NetworkUtils.getAbsoluteURL(rc.getNameSpace(), data.getImgUrl()), data.getName(), data.getAuthor());
+ }
+ tvBookName.setText(data.getName());
+ if (!StringHelper.isEmpty(data.getAuthor())) {
+ tvAuthor.setText(data.getAuthor());
+ }else {
+ tvAuthor.setText("");
+ }
+ initTagList(data);
+ if (!StringHelper.isEmpty(data.getNewestChapterTitle())) {
+ tvNewestChapter.setText(getContext().getString(R.string.newest_chapter, data.getNewestChapterTitle()));
+ } else {
+ data.setNewestChapterTitle("");
+ tvNewestChapter.setText("");
+ }
+ if (!StringHelper.isEmpty(data.getDesc())) {
+ tvDesc.setText(String.format("简介:%s", data.getDesc()));
+ } else {
+ data.setDesc("");
+ tvDesc.setText("");
+ }
+ if (!StringHelper.isEmpty(source.getSourceName()) && !"未知书源".equals(source.getSourceName()))
+ tvSource.setText(String.format("书源:%s", source.getSourceName()));
+ if (needGetInfo(data) && rc instanceof BookInfoCrawler) {
+ Log.i(data.getName(), "initOtherInfo");
+ BookInfoCrawler bic = (BookInfoCrawler) rc;
+ BookApi.getBookInfo(data, bic).compose(RxUtils::toSimpleSingle)
+ .subscribe(new MyObserver() {
+ @Override
+ public void onNext(@NotNull Book book) {
+ initOtherInfo(book, rc);
+ }
+ });
+ }
+ }
+
+ private void initOtherInfo(Book book, ReadCrawler rc) {
+ //简介
+ if (StringHelper.isEmpty(tvDesc.getText().toString())) {
+ tvDesc.setText(String.format("简介:%s", book.getDesc()));
+ }
+ if (StringHelper.isEmpty(tvNewestChapter.getText().toString())) {
+ tvNewestChapter.setText(getContext().getString(R.string.newest_chapter, book.getNewestChapterTitle()));
+ }
+ if (!StringHelper.isEmpty(book.getAuthor())) {
+ tvAuthor.setText(book.getAuthor());
+ }
+ //图片
+ if (!App.isDestroy((Activity) getContext())) {
+ ivBookImg.load(NetworkUtils.getAbsoluteURL(rc.getNameSpace(), book.getImgUrl()), book.getName(), book.getAuthor());
+ }
+ }
+
+ private void initTagList(Book data) {
+ tagList.clear();
+ String type = data.getType();
+ if (!StringHelper.isEmpty(type))
+ tagList.add("0:" + type);
+ String wordCount = data.getWordCount();
+ if (!StringHelper.isEmpty(wordCount))
+ tagList.add("1:" + wordCount);
+ String status = data.getStatus();
+ if (!StringHelper.isEmpty(status))
+ tagList.add("2:" + status);
+ if (tagList.size() == 0) {
+ tflBookTag.setVisibility(View.GONE);
+ } else {
+ tflBookTag.setVisibility(View.VISIBLE);
+ tflBookTag.setAdapter(new BookTagAdapter(getContext(), tagList, 11));
+ }
+ }
+ private boolean needGetInfo(Book bookBean) {
+ if (StringHelper.isEmpty(bookBean.getAuthor())) return true;
+ if (StringHelper.isEmpty(bookBean.getType())) return true;
+ if (StringHelper.isEmpty(bookBean.getDesc())) return true;
+ if (StringHelper.isEmpty(bookBean.getNewestChapterTitle())) return true;
+ return StringHelper.isEmpty(bookBean.getImgUrl());
+ }
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/FindSourceHolder.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/FindSourceHolder.java
new file mode 100644
index 0000000..ee0cac7
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/FindSourceHolder.java
@@ -0,0 +1,36 @@
+package xyz.fycz.myreader.ui.adapter.holder;
+
+import android.content.Intent;
+import android.widget.TextView;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import xyz.fycz.myreader.R;
+import xyz.fycz.myreader.base.BitIntentDataManager;
+import xyz.fycz.myreader.base.adapter.ViewHolderImpl;
+import xyz.fycz.myreader.greendao.entity.rule.BookSource;
+import xyz.fycz.myreader.ui.activity.FindBookActivity;
+
+/**
+ * @author fengyue
+ * @date 2021/7/22 22:27
+ */
+public class FindSourceHolder extends ViewHolderImpl {
+
+ private TextView tvName;
+
+ @Override
+ protected int getItemLayoutId() {
+ return R.layout.item_find_source;
+ }
+
+ @Override
+ public void initView() {
+ tvName = findById(R.id.tv_name);
+ }
+
+ @Override
+ public void onBind(RecyclerView.ViewHolder holder, BookSource data, int pos) {
+ tvName.setText(data.getSourceName());
+ }
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/SearchBookHolder.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/SearchBookHolder.java
index 5ba1d59..4fe9049 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/SearchBookHolder.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/SearchBookHolder.java
@@ -3,6 +3,7 @@ package xyz.fycz.myreader.ui.adapter.holder;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.util.Log;
+import android.view.View;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
@@ -79,7 +80,7 @@ public class SearchBookHolder extends ViewHolderImpl {
@Override
public void onBind(RecyclerView.ViewHolder holder, SearchBookBean data, int pos) {
List aBooks = mBooks.getValues(data);
- if (aBooks == null || aBooks.size() == 0){
+ if (aBooks == null || aBooks.size() == 0) {
aBooks = new ArrayList<>();
aBooks.add(searchBookBean2Book(data));
}
@@ -88,37 +89,34 @@ public class SearchBookHolder extends ViewHolderImpl {
BookSource source = BookSourceManager.getBookSourceByStr(book.getSource());
ReadCrawler rc = ReadCrawlerUtil.getReadCrawler(source);
books2SearchBookBean(data, aBooks);
- if (!StringHelper.isEmpty(data.getImgUrl())) {
- if (!App.isDestroy((Activity) getContext())) {
- ivBookImg.load(NetworkUtils.getAbsoluteURL(rc.getNameSpace(), data.getImgUrl()), data.getName(), data.getAuthor());
- }
- }else {
+ if (StringHelper.isEmpty(data.getImgUrl())) {
data.setImgUrl("");
}
+ if (!App.isDestroy((Activity) getContext())) {
+ ivBookImg.load(NetworkUtils.getAbsoluteURL(rc.getNameSpace(), data.getImgUrl()), data.getName(), data.getAuthor());
+ }
KeyWordUtils.setKeyWord(tvBookName, data.getName(), keyWord);
if (!StringHelper.isEmpty(data.getAuthor())) {
KeyWordUtils.setKeyWord(tvAuthor, data.getAuthor(), keyWord);
+ } else {
+ tvAuthor.setText("");
}
initTagList(data);
if (!StringHelper.isEmpty(data.getLastChapter())) {
tvNewestChapter.setText(getContext().getString(R.string.newest_chapter, data.getLastChapter()));
- }else {
+ } else {
data.setLastChapter("");
+ tvNewestChapter.setText("");
}
if (!StringHelper.isEmpty(data.getDesc())) {
tvDesc.setText(String.format("简介:%s", data.getDesc()));
- }else {
+ } else {
data.setDesc("");
+ tvDesc.setText("");
}
tvSource.setText(getContext().getString(R.string.source_title_num, source.getSourceName(), bookCount));
App.getHandler().postDelayed(() -> {
if (needGetInfo(data) && rc instanceof BookInfoCrawler) {
- if (tvBookName.getTag() == null || !(Boolean) tvBookName.getTag()) {
- tvBookName.setTag(true);
- } else {
- initOtherInfo(data, rc);
- return;
- }
Log.i(data.getName(), "initOtherInfo");
BookInfoCrawler bic = (BookInfoCrawler) rc;
searchEngine.getBookInfo(book, bic, isSuccess -> {
@@ -127,8 +125,6 @@ public class SearchBookHolder extends ViewHolderImpl {
books.add(book);
books2SearchBookBean(data, books);
initOtherInfo(data, rc);
- } else {
- tvBookName.setTag(false);
}
});
}
@@ -163,7 +159,12 @@ public class SearchBookHolder extends ViewHolderImpl {
String status = data.getStatus();
if (!StringHelper.isEmpty(status))
tagList.add("2:" + status);
- tflBookTag.setAdapter(new BookTagAdapter(activity, tagList, 11));
+ if (tagList.size() == 0) {
+ tflBookTag.setVisibility(View.GONE);
+ } else {
+ tflBookTag.setVisibility(View.VISIBLE);
+ tflBookTag.setAdapter(new BookTagAdapter(activity, tagList, 11));
+ }
}
private void books2SearchBookBean(SearchBookBean bookBean, List books) {
@@ -233,7 +234,7 @@ public class SearchBookHolder extends ViewHolderImpl {
}
}
- private Book searchBookBean2Book(SearchBookBean bean){
+ private Book searchBookBean2Book(SearchBookBean bean) {
Book book = new Book();
book.setName(bean.getName());
book.setAuthor(bean.getAuthor());
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/fragment/DIYSourceFragment.java b/app/src/main/java/xyz/fycz/myreader/ui/fragment/DIYSourceFragment.java
index a3b2916..beeb85b 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/fragment/DIYSourceFragment.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/fragment/DIYSourceFragment.java
@@ -226,6 +226,7 @@ public class DIYSourceFragment extends BaseFragment {
@Override
public void onSubscribe(Disposable d) {
importSourceDis = d;
+ addDisposable(d);
}
@Override
@@ -281,6 +282,10 @@ public class DIYSourceFragment extends BaseFragment {
}
emitter.onSuccess(sourceBeanList);
}).compose(RxUtils::toSimpleSingle).subscribe(new MySingleObserver>() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
@Override
public void onSuccess(@NonNull List sources) {
mBookSources = sources;
@@ -391,6 +396,10 @@ public class DIYSourceFragment extends BaseFragment {
emitter.onSuccess(FileUtils.writeText(GsonExtensionsKt.getGSON().toJson(sources),
FileUtils.getFile(APPCONST.FILE_DIR + "BookSources.json")));
}).compose(RxUtils::toSimpleSingle).subscribe(new MySingleObserver() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
@Override
public void onSuccess(@NonNull Boolean aBoolean) {
if (aBoolean) {
@@ -418,6 +427,10 @@ public class DIYSourceFragment extends BaseFragment {
emitter.onError(new Exception("书源文件写出失败"));
}
}).compose(RxUtils::toSimpleSingle).subscribe(new MySingleObserver() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
@Override
public void onSuccess(@NonNull File share) {
ShareUtils.share(sourceActivity, share, "书源分享", "text/plain");
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/fragment/FindBook1Fragment.java b/app/src/main/java/xyz/fycz/myreader/ui/fragment/FindBook1Fragment.java
new file mode 100644
index 0000000..31f0b4d
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/ui/fragment/FindBook1Fragment.java
@@ -0,0 +1,66 @@
+package xyz.fycz.myreader.ui.fragment;
+
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.PopupMenu;
+import androidx.fragment.app.Fragment;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import xyz.fycz.myreader.base.BaseFragment;
+import xyz.fycz.myreader.base.LazyFragment;
+import xyz.fycz.myreader.databinding.FragmentFindBook1Binding;
+import xyz.fycz.myreader.entity.FindKind;
+import xyz.fycz.myreader.ui.adapter.TabFragmentPageAdapter;
+import xyz.fycz.myreader.webapi.crawler.base.FindCrawler;
+
+/**
+ * @author fengyue
+ * @date 2021/7/21 23:06
+ */
+public class FindBook1Fragment extends LazyFragment {
+ private FragmentFindBook1Binding binding;
+ private List kinds;
+ private FindCrawler findCrawler;
+ private PopupMenu kindMenu;
+
+ public FindBook1Fragment(List kinds, FindCrawler findCrawler) {
+ this.kinds = kinds;
+ this.findCrawler = findCrawler;
+ }
+ @Override
+ public void lazyInit() {
+ kindMenu = new PopupMenu(getContext(), binding.ivMenu, Gravity.END);
+ TabFragmentPageAdapter adapter = new TabFragmentPageAdapter(getChildFragmentManager());
+ for (int i = 0, kindsSize = kinds.size(); i < kindsSize; i++) {
+ FindKind kind = kinds.get(i);
+ adapter.addFragment(new FindBook2Fragment(kind, findCrawler), kind.getName());
+ kindMenu.getMenu().add(0, 0, i, kind.getName());
+ }
+ binding.tabVp.setAdapter(adapter);
+ binding.tabVp.setOffscreenPageLimit(3);
+ binding.tabTlIndicator.setUpWithViewPager(binding.tabVp);
+ kindMenu.setOnMenuItemClickListener(item -> {
+ binding.tabTlIndicator.setCurrentItem(item.getOrder(), true);
+ return true;
+ });
+ binding.ivMenu.setOnClickListener(v -> kindMenu.show());
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull @NotNull LayoutInflater inflater, @Nullable @org.jetbrains.annotations.Nullable ViewGroup container, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
+ binding = FragmentFindBook1Binding.inflate(inflater, container, false);
+ return binding.getRoot();
+ }
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/fragment/FindBook2Fragment.java b/app/src/main/java/xyz/fycz/myreader/ui/fragment/FindBook2Fragment.java
new file mode 100644
index 0000000..fc6f7a9
--- /dev/null
+++ b/app/src/main/java/xyz/fycz/myreader/ui/fragment/FindBook2Fragment.java
@@ -0,0 +1,177 @@
+package xyz.fycz.myreader.ui.fragment;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.LinearLayoutManager;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+import io.reactivex.disposables.Disposable;
+import xyz.fycz.myreader.base.BaseFragment;
+import xyz.fycz.myreader.base.BitIntentDataManager;
+import xyz.fycz.myreader.base.LazyFragment;
+import xyz.fycz.myreader.base.adapter.BaseListAdapter;
+import xyz.fycz.myreader.base.adapter.IViewHolder;
+import xyz.fycz.myreader.base.observer.MyObserver;
+import xyz.fycz.myreader.common.APPCONST;
+import xyz.fycz.myreader.databinding.FragmentFindBook2Binding;
+import xyz.fycz.myreader.entity.FindKind;
+import xyz.fycz.myreader.greendao.entity.Book;
+import xyz.fycz.myreader.greendao.service.BookService;
+import xyz.fycz.myreader.ui.activity.BookDetailedActivity;
+import xyz.fycz.myreader.ui.activity.BookstoreActivity;
+import xyz.fycz.myreader.ui.adapter.holder.FindBookHolder;
+import xyz.fycz.myreader.ui.dialog.SourceExchangeDialog;
+import xyz.fycz.myreader.util.ToastUtils;
+import xyz.fycz.myreader.util.utils.RxUtils;
+import xyz.fycz.myreader.webapi.BookApi;
+import xyz.fycz.myreader.webapi.crawler.base.FindCrawler;
+import xyz.fycz.myreader.widget.RefreshLayout;
+
+/**
+ * @author fengyue
+ * @date 2021/7/21 23:06
+ */
+public class FindBook2Fragment extends LazyFragment {
+ private FragmentFindBook2Binding binding;
+ private FindKind kind;
+ private FindCrawler findCrawler;
+ private int page = 1;
+ private BaseListAdapter findBookAdapter;
+ private SourceExchangeDialog mSourceDia;
+
+
+ public FindBook2Fragment(FindKind kind, FindCrawler findCrawler) {
+ this.kind = kind;
+ this.findCrawler = findCrawler;
+ }
+
+ @Override
+ public void lazyInit() {
+ initData();
+ initWidget();
+ }
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull @NotNull LayoutInflater inflater, @Nullable @org.jetbrains.annotations.Nullable ViewGroup container, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
+ binding = FragmentFindBook2Binding.inflate(inflater, container, false);
+ return binding.getRoot();
+ }
+
+ protected void initData() {
+ findBookAdapter = new BaseListAdapter() {
+ @Override
+ protected IViewHolder createViewHolder(int viewType) {
+ return new FindBookHolder();
+ }
+ };
+ binding.rvFindBooks.setLayoutManager(new LinearLayoutManager(getContext()));
+ binding.rvFindBooks.setAdapter(findBookAdapter);
+ page = 1;
+ loadBooks();
+ }
+
+ protected void initWidget() {
+ binding.loading.setOnReloadingListener(() -> {
+ page = 1;
+ loadBooks();
+ });
+ //小说列表下拉加载更多事件
+ binding.srlFindBooks.setOnLoadMoreListener(refreshLayout -> loadBooks());
+
+ //小说列表上拉刷新事件
+ binding.srlFindBooks.setOnRefreshListener(refreshLayout -> {
+ page = 1;
+ loadBooks();
+ });
+
+ findBookAdapter.setOnItemClickListener((view, pos) -> {
+ Book book = findBookAdapter.getItem(pos);
+ if (!findCrawler.needSearch()) {
+ goToBookDetail(book);
+ } else {
+ if (BookService.getInstance().isBookCollected(book)) {
+ goToBookDetail(book);
+ return;
+ }
+ mSourceDia = new SourceExchangeDialog(getActivity(), book);
+ mSourceDia.setOnSourceChangeListener((bean, pos1) -> {
+ Intent intent = new Intent(getContext(), BookDetailedActivity.class);
+ BitIntentDataManager.getInstance().putData(intent, mSourceDia.getaBooks());
+ intent.putExtra(APPCONST.SOURCE_INDEX, pos1);
+ getActivity().startActivity(intent);
+ mSourceDia.dismiss();
+ });
+ mSourceDia.show();
+ }
+ });
+ }
+
+ private void loadBooks() {
+ BookApi.findBooks(kind, findCrawler, page).compose(RxUtils::toSimpleSingle).subscribe(new MyObserver>() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
+
+ @Override
+ public void onNext(@NotNull List books) {
+ binding.loading.showFinish();
+ if (page == 1) {
+ if (books.size() == 0) {
+ binding.srlFindBooks.finishRefreshWithNoMoreData();
+ } else {
+ findBookAdapter.refreshItems(books);
+ binding.srlFindBooks.finishRefresh();
+ }
+ } else {
+ if (books.size() == 0) {
+ binding.srlFindBooks.finishLoadMoreWithNoMoreData();
+ } else {
+ findBookAdapter.addItems(books);
+ binding.srlFindBooks.finishLoadMore();
+ }
+ }
+ page++;
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ e.printStackTrace();
+ if (page == 1) {
+ ToastUtils.showError("数据加载失败\n" + e.getLocalizedMessage());
+ binding.loading.showError();
+ binding.srlFindBooks.finishRefresh();
+ } else {
+ if (e.getMessage()!= null && e.getMessage().contains("没有下一页")) {
+ binding.srlFindBooks.finishLoadMoreWithNoMoreData();
+ } else {
+ ToastUtils.showError("数据加载失败\n" + e.getLocalizedMessage());
+ binding.srlFindBooks.finishLoadMore();
+ }
+ }
+ }
+ });
+ }
+
+ /**
+ * 前往书籍详情
+ *
+ * @param book
+ */
+ private void goToBookDetail(Book book) {
+ Intent intent = new Intent(getContext(), BookDetailedActivity.class);
+ BitIntentDataManager.getInstance().putData(intent, book);
+ getActivity().startActivity(intent);
+ }
+
+}
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/fragment/FindFragment.java b/app/src/main/java/xyz/fycz/myreader/ui/fragment/FindFragment.java
index 2272590..0d8fb47 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/fragment/FindFragment.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/fragment/FindFragment.java
@@ -1,37 +1,45 @@
package xyz.fycz.myreader.ui.fragment;
-import android.content.ClipData;
-import android.content.ClipboardManager;
-import android.content.Context;
import android.content.Intent;
-import android.net.Uri;
import android.os.Bundle;
+import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import androidx.recyclerview.widget.LinearLayoutManager;
+
import org.jetbrains.annotations.NotNull;
+import java.util.ArrayList;
+import java.util.List;
+
+import io.reactivex.Observable;
+import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Single;
import io.reactivex.SingleOnSubscribe;
-import xyz.fycz.myreader.application.App;
+import io.reactivex.disposables.Disposable;
import xyz.fycz.myreader.base.BaseFragment;
+import xyz.fycz.myreader.base.BitIntentDataManager;
+import xyz.fycz.myreader.base.adapter.BaseListAdapter;
+import xyz.fycz.myreader.base.adapter.IViewHolder;
+import xyz.fycz.myreader.base.observer.MyObserver;
import xyz.fycz.myreader.base.observer.MySingleObserver;
-import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.common.URLCONST;
import xyz.fycz.myreader.databinding.FragmentFindBinding;
import xyz.fycz.myreader.entity.Quotation;
-import xyz.fycz.myreader.ui.activity.BookstoreActivity;
-import xyz.fycz.myreader.util.ToastUtils;
+import xyz.fycz.myreader.greendao.entity.rule.BookSource;
+import xyz.fycz.myreader.model.sourceAnalyzer.BookSourceManager;
+import xyz.fycz.myreader.ui.activity.FindBookActivity;
+import xyz.fycz.myreader.ui.adapter.holder.FindSourceHolder;
import xyz.fycz.myreader.util.utils.GsonExtensionsKt;
-import xyz.fycz.myreader.util.utils.ImageLoader;
import xyz.fycz.myreader.util.utils.OkHttpUtils;
import xyz.fycz.myreader.util.utils.RxUtils;
import xyz.fycz.myreader.webapi.crawler.base.FindCrawler;
-import xyz.fycz.myreader.webapi.crawler.find.Ben100FindCrawler;
-import xyz.fycz.myreader.webapi.crawler.find.MiaoBiFindCrawler;
+import xyz.fycz.myreader.webapi.crawler.find.MiaoBiGeFindCrawler;
import xyz.fycz.myreader.webapi.crawler.find.QB5FindCrawler;
-import xyz.fycz.myreader.webapi.crawler.find.QiDianMobileRank;
+import xyz.fycz.myreader.webapi.crawler.find.QiDianFindCrawler;
+import xyz.fycz.myreader.widget.DividerItemDecoration;
/**
* @author fengyue
@@ -40,6 +48,7 @@ import xyz.fycz.myreader.webapi.crawler.find.QiDianMobileRank;
public class FindFragment extends BaseFragment {
private FragmentFindBinding binding;
+ private BaseListAdapter findSourcesAdapter;
@Override
protected View bindView(LayoutInflater inflater, ViewGroup container) {
@@ -47,6 +56,52 @@ public class FindFragment extends BaseFragment {
return binding.getRoot();
}
+ @Override
+ protected void initData(Bundle savedInstanceState) {
+ Observable.create((ObservableOnSubscribe>) emitter -> {
+ List findSources = new ArrayList<>();
+ List sources = BookSourceManager.getEnabledBookSourceByOrderNum();
+ for (BookSource source : sources){
+ if (source.getFindRule() != null && !TextUtils.isEmpty(source.getFindRule().getUrl())){
+ findSources.add(source);
+ }
+ }
+ emitter.onNext(findSources);
+ emitter.onComplete();
+ }).compose(RxUtils::toSimpleSingle).subscribe(new MyObserver>() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
+
+ @Override
+ public void onNext(@NotNull List findSources) {
+ initFindSources(findSources);
+ }
+ });
+ }
+
+ private void initFindSources(List findSources) {
+ findSourcesAdapter = new BaseListAdapter() {
+ @Override
+ protected IViewHolder createViewHolder(int viewType) {
+ return new FindSourceHolder();
+ }
+ };
+ binding.rvFindSources.setLayoutManager(new LinearLayoutManager(getContext()));
+ binding.rvFindSources.setAdapter(findSourcesAdapter);
+ //设置分割线
+ binding.rvFindSources.addItemDecoration(new DividerItemDecoration(getContext()));
+
+ findSourcesAdapter.setOnItemClickListener((view, pos) -> {
+ Intent intent = new Intent(getContext(), FindBookActivity.class);
+ BitIntentDataManager.getInstance().putData(intent, findSourcesAdapter.getItem(pos));
+ getContext().startActivity(intent);
+ });
+
+ findSourcesAdapter.refreshItems(findSources);
+ }
+
@Override
protected void initWidget(Bundle savedInstanceState) {
getQuotation();
@@ -56,21 +111,16 @@ public class FindFragment extends BaseFragment {
protected void initClick() {
super.initClick();
binding.findRlQuotation.setOnClickListener(v -> getQuotation());
- binding.findRlQidianTop.setOnClickListener(v -> comeToBookstore(new QiDianMobileRank(false)));
- binding.findRlQidianNsTop.setOnClickListener(v -> comeToBookstore(new QiDianMobileRank(true)));
- //binding.findRlXs7Top.setOnClickListener(v -> comeToBookstore(new XS7Rank()));
- binding.findRlQidianSort.setOnClickListener(v -> comeToBookstore(new QiDianMobileRank(false, true)));
- binding.findRlQidianNsSort.setOnClickListener(v -> comeToBookstore(new QiDianMobileRank(true, true)));
+ binding.findRlQidian.setOnClickListener(v -> comeToBookstore(new QiDianFindCrawler(false)));
+ binding.findRlQidianNs.setOnClickListener(v -> comeToBookstore(new QiDianFindCrawler(true)));
+ binding.findRlMiaoquStore.setOnClickListener(v -> comeToBookstore(new MiaoBiGeFindCrawler()));
binding.findRlQb5Store.setOnClickListener(v -> comeToBookstore(new QB5FindCrawler()));
- binding.findRlBen100Store.setOnClickListener(v -> comeToBookstore(new Ben100FindCrawler()));
- binding.findRlMiaoquStore.setOnClickListener(v -> comeToBookstore(new MiaoBiFindCrawler()));
- //binding.findRlXs7Store.setOnClickListener(v -> comeToBookstore(new XS7ReadCrawler()));
}
private void comeToBookstore(FindCrawler findCrawler) {
- Intent intent = new Intent(getContext(), BookstoreActivity.class);
- intent.putExtra(APPCONST.FIND_CRAWLER, findCrawler);
+ Intent intent = new Intent(getContext(), FindBookActivity.class);
+ BitIntentDataManager.getInstance().putData(intent, findCrawler);
startActivity(intent);
}
@@ -79,6 +129,10 @@ public class FindFragment extends BaseFragment {
String json = OkHttpUtils.getHtml(URLCONST.QUOTATION);
emitter.onSuccess(GsonExtensionsKt.getGSON().fromJson(json, Quotation.class));
}).compose(RxUtils::toSimpleSingle).subscribe(new MySingleObserver() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
@Override
public void onSuccess(@NotNull Quotation q) {
binding.tvQuotation.setText(q.getHitokoto());
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/fragment/LocalSourceFragment.java b/app/src/main/java/xyz/fycz/myreader/ui/fragment/LocalSourceFragment.java
index a9e2c94..9558cb9 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/fragment/LocalSourceFragment.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/fragment/LocalSourceFragment.java
@@ -12,6 +12,7 @@ import java.util.List;
import io.reactivex.Single;
import io.reactivex.SingleOnSubscribe;
import io.reactivex.annotations.NonNull;
+import io.reactivex.disposables.Disposable;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.base.BaseFragment;
import xyz.fycz.myreader.base.observer.MySingleObserver;
@@ -109,6 +110,10 @@ public class LocalSourceFragment extends BaseFragment {
emitter.onSuccess(true);
}).compose(RxUtils::toSimpleSingle)
.subscribe(new MySingleObserver() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
@Override
public void onSuccess(@NonNull Boolean aBoolean) {
mAdapter.notifyDataSetChanged();
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java b/app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java
index db21487..fb17d57 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java
@@ -26,6 +26,7 @@ import java.util.Date;
import io.reactivex.Single;
import io.reactivex.SingleOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.App;
@@ -176,6 +177,10 @@ public class MineFragment extends BaseFragment {
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new MySingleObserver>() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
@Override
public void onSuccess(ArrayList strings) {
if (!WebDavHelp.INSTANCE.showRestoreDialog(getContext(), strings, new Restore.CallBack() {
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/fragment/WebDavFragment.java b/app/src/main/java/xyz/fycz/myreader/ui/fragment/WebDavFragment.java
index 5b91e16..e9490f6 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/fragment/WebDavFragment.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/fragment/WebDavFragment.java
@@ -15,6 +15,7 @@ import java.util.ArrayList;
import io.reactivex.Single;
import io.reactivex.SingleOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.SysManager;
@@ -116,6 +117,10 @@ public class WebDavFragment extends BaseFragment {
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new MySingleObserver>() {
+ @Override
+ public void onSubscribe(Disposable d) {
+ addDisposable(d);
+ }
@Override
public void onSuccess(ArrayList strings) {
if (!WebDavHelp.INSTANCE.showRestoreDialog(getContext(), strings, new Restore.CallBack() {
diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java
index 66ff6ce..e673ffb 100644
--- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java
+++ b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java
@@ -379,6 +379,11 @@ public class BookcasePresenter implements BasePresenter {
emitter.onNext(book);
emitter.onComplete();
})).compose(RxUtils::toSimpleSingle).subscribe(new MyObserver