mTreeDatas) {
+ super(fm);
+ this.mTreeDatas = mTreeDatas;
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ return TreeListFragment.instantiate(mTreeDatas.get(position).getId());
+ }
+
+ @Override
+ public int getCount() {
+ return mTreeDatas != null ? mTreeDatas.size() : 0;
+ }
+
+ @Override
+ public CharSequence getPageTitle(int position) {
+ return mTreeDatas.get(position).getName();
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseAbListActivity.java b/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseAbListActivity.java
new file mode 100644
index 0000000..0d2a864
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseAbListActivity.java
@@ -0,0 +1,285 @@
+package com.kdp.wanandroidclient.ui.base;
+
+import android.annotation.SuppressLint;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+import com.kdp.wanandroidclient.R;
+import com.kdp.wanandroidclient.common.Const;
+import com.kdp.wanandroidclient.event.Event;
+import com.kdp.wanandroidclient.event.RxEvent;
+import com.kdp.wanandroidclient.ui.adapter.BaseListAdapter;
+import com.kdp.wanandroidclient.ui.core.presenter.BasePresenter;
+import com.kdp.wanandroidclient.ui.core.view.IPageLoadDataView;
+import com.kdp.wanandroidclient.utils.ViewAnimatorHelper;
+import com.kdp.wanandroidclient.widget.StatusLayout;
+import com.kdp.wanandroidclient.widget.LMRecyclerView;
+import com.kdp.wanandroidclient.widget.NoAlphaItemAnimator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Activity 列表基类
+
+ */
+
+public abstract class BaseAbListActivity extends BasePresenterActivity
implements LMRecyclerView.OnFooterAutoLoadMoreListener, IPageLoadDataView {
+
+
+ protected StatusLayout mStatusLayout;
+ protected SwipeRefreshLayout mRefreshLayout;
+ protected LMRecyclerView mRecyclerView;
+ private FloatingActionButton btn_scroll_top;
+ protected BaseListAdapter mListAdapter;
+ private ViewAnimatorHelper viewAnimatorHelper;
+ protected int page;
+ protected int state = -1;
+ protected boolean isAutoLoadMore = true;//是否显示自动加载
+ protected List mListData = new ArrayList<>();
+
+ @SuppressLint("RestrictedApi")
+ @Override
+ protected void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ btn_scroll_top.setVisibility(View.VISIBLE);
+ btn_scroll_top.setOnClickListener(onScrollTopListener);
+ viewAnimatorHelper = new ViewAnimatorHelper();
+ viewAnimatorHelper.bindView(btn_scroll_top);
+ mRefreshLayout.setOnRefreshListener(mOnRefreshListener);
+ mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
+ mRecyclerView.setItemAnimator(new NoAlphaItemAnimator());
+ mRecyclerView.addOnScrollListener(onScrollListener);
+ setCanLoadMore(isCanLoadMore());
+ mRecyclerView.addFooterAutoLoadMoreListener(this);
+ mListAdapter = getListAdapter();
+ mStatusLayout.showLoding();
+ if (mListAdapter != null) {
+ mRecyclerView.addHeaderView(initHeaderView());
+ mRecyclerView.setAdapter(mListAdapter);
+ loadDatas();
+ }
+ }
+
+ /**
+ * 初始化控件
+ */
+ @Override
+ protected void initViews() {
+ mRefreshLayout = findViewById(R.id.refreshLayout);
+ mStatusLayout = findViewById(R.id.containerLayout);
+ mRecyclerView = findViewById(R.id.recyclerView);
+ btn_scroll_top = findViewById(R.id.btn_scroll_top);
+ }
+
+ private RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+ if (dy > 0 && btn_scroll_top.getVisibility() != View.INVISIBLE && !viewAnimatorHelper.isAnimating()){
+ viewAnimatorHelper.hideFloatActionButton();
+ }else if (dy < 0 && btn_scroll_top.getVisibility() != View.VISIBLE){
+ viewAnimatorHelper.showFloatActionButton();
+ }
+ }
+ };
+
+ private View.OnClickListener onScrollTopListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mRecyclerView.smoothScrollToPosition(0);
+ }
+ };
+ /**
+ * 加载Layout布局
+ * @return
+ */
+ @Override
+ protected int getLayoutId() {
+ return R.layout.include_recycler_list;
+ }
+
+ @Override
+ public List getData() {
+ return mListData;
+ }
+
+
+
+ /**
+ * 请求数据成功展示内容
+ */
+ @Override
+ public void showContent() {
+ mStatusLayout.showContent();
+ mListAdapter.notifyAllDatas(mListData, mRecyclerView);
+ }
+
+ /**
+ * 下拉刷新监听
+ */
+ private SwipeRefreshLayout.OnRefreshListener mOnRefreshListener = new SwipeRefreshLayout.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ refreshData();
+ }
+ };
+
+
+ /**
+ * 刷新数据,回到第一页
+ */
+ public void refreshData() {
+ state = Const.PAGE_STATE.STATE_REFRESH;
+ isAutoLoadMore = true;
+ page = getFirstPage();
+ loadDatas();
+ }
+
+ /**
+ * 滑到底部开始加载更多数据
+ */
+ @Override
+ public void loadMore() {
+ if (!isAutoLoadMore) return;
+ state = Const.PAGE_STATE.STATE_LOAD_MORE;
+ loadDatas();
+ }
+
+ /**
+ * 底部加载更多失败,点击重新加载
+ */
+ @Override
+ public void reLoadMore() {
+ isAutoLoadMore = true;
+ loadMore();
+ }
+
+
+ /**
+ * 清空当前列表数据
+ */
+ @Override
+ public void clearListData() {
+ mListData.clear();
+ }
+
+ /**
+ * 开始自动加载更多
+ */
+ @Override
+ public void autoLoadMore() {
+ mRecyclerView.showLoadMore();
+ page++;
+ isAutoLoadMore = true;
+ }
+
+ /**
+ * 显示没有更多数据了
+ */
+ @Override
+ public void showNoMore() {
+ mRecyclerView.showNoMoreData();
+ isAutoLoadMore = false;
+ }
+
+
+ /**
+ * 数据加载异常处理
+ */
+ @Override
+ public void showError() {
+ isAutoLoadMore = false;
+ //如果是加载更多出现异常,那么底部就显示点击重新加载;
+ // 否则,就清空数据,显示没有数据
+ if (state == Const.PAGE_STATE.STATE_LOAD_MORE) {
+ mRecyclerView.showLoadMoreError();
+ mListAdapter.notifyAllDatas(mListData, mRecyclerView);
+ } else {
+ mStatusLayout.showError();
+ }
+
+ }
+
+ /**
+ * 当前请求页
+ * @return
+ */
+ public int getPage() {
+ return page;
+ }
+
+ /**
+ * 显示Loading
+ * @param msg
+ */
+ @Override
+ public void showLoading(String msg) {
+ if (state == Const.PAGE_STATE.STATE_REFRESH)
+ setRefreshing(true);
+ }
+
+ @Override
+ public void hideLoading() {
+ setRefreshing(false);
+ }
+
+ /**
+ * 是否能加载更多
+ * @param isCanLoadMore
+ */
+ public void setCanLoadMore(boolean isCanLoadMore) {
+ mRecyclerView.setCanLoadMore(isCanLoadMore);
+ }
+
+ /**
+ * 是否禁用刷新
+ * @param isEnableRefresh
+ */
+ public void setRefreshEnable(boolean isEnableRefresh) {
+ mRefreshLayout.setEnabled(isEnableRefresh);
+ }
+
+ /**
+ * 没有数据时显示
+ */
+ @Override
+ public void showEmpty() {
+ mStatusLayout.showEmpty();
+ }
+
+
+ protected void setRefreshing(final boolean isRefrshing) {
+ mRefreshLayout.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mRefreshLayout.setRefreshing(isRefrshing);
+ }
+ }, 100);
+ }
+
+ @Override
+ public int getFirstPage() {
+ return 0;
+ }
+
+ /**
+ * 是否允许自动加载更多
+ * @return
+ */
+ protected boolean isCanLoadMore(){
+ return false;
+ }
+
+ protected View initHeaderView(){
+ return null;
+ }
+
+ protected abstract void loadDatas();
+
+ protected abstract BaseListAdaptergetListAdapter();
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseAbListFragment.java b/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseAbListFragment.java
new file mode 100644
index 0000000..8bc7c2a
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseAbListFragment.java
@@ -0,0 +1,289 @@
+package com.kdp.wanandroidclient.ui.base;
+
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
+import android.view.View;
+
+import com.kdp.wanandroidclient.R;
+import com.kdp.wanandroidclient.common.Const;
+import com.kdp.wanandroidclient.event.Event;
+import com.kdp.wanandroidclient.event.RxEvent;
+import com.kdp.wanandroidclient.ui.adapter.BaseListAdapter;
+import com.kdp.wanandroidclient.ui.core.presenter.BasePresenter;
+import com.kdp.wanandroidclient.ui.core.view.IPageLoadDataView;
+import com.kdp.wanandroidclient.utils.ToastUtils;
+import com.kdp.wanandroidclient.widget.StatusLayout;
+import com.kdp.wanandroidclient.widget.LMRecyclerView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * fragment列表基类
+ * author: 曾文海
+ * date: 2023/5/31
+ */
+
+public abstract class BaseAbListFragment extends BasePresenterFragment
implements LMRecyclerView.OnFooterAutoLoadMoreListener, IPageLoadDataView {
+
+ protected StatusLayout mStatusLayout;
+ protected SwipeRefreshLayout mRefreshLayout;
+ protected LMRecyclerView mRecyclerView;
+ protected BaseListAdapter mListAdapter;
+ protected int page = getFirstPage();
+ protected int state = -1;
+ protected boolean isAutoLoadMore = true;//是否开启自动加载
+ private boolean isPreload; //是否已经预加载完成
+ private boolean isVisible; //是否可见
+ private boolean isFirst = true;//是否第一次加载数据
+ private boolean isEnableLazy = false; //是否开启懒加载
+ protected List mListData = new ArrayList<>();
+
+
+ @Override
+ protected void initViews(View view) {
+ mRefreshLayout = view.findViewById(R.id.refreshLayout);
+ mStatusLayout = view.findViewById(R.id.containerLayout);
+ mRecyclerView = view.findViewById(R.id.recyclerView);
+ }
+
+
+ @Override
+ public List getData() {
+ return mListData;
+ }
+
+ /**
+ * 请求数据成功展示内容
+ */
+ @Override
+ public void showContent() {
+ mStatusLayout.showContent();
+ mListAdapter.notifyAllDatas(mListData, mRecyclerView);
+ }
+
+
+ @Override
+ protected int getLayoutId() {
+ return R.layout.include_recycler_list;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ mRefreshLayout.setOnRefreshListener(mOnRefreshListener);
+ mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
+ mRecyclerView.setCanLoadMore(isCanLoadMore());
+ mRecyclerView.addFooterAutoLoadMoreListener(this);
+ mListAdapter = getListAdapter();
+ if (mListAdapter != null) {
+ mRecyclerView.addHeaderView(initHeaderView());
+ mRecyclerView.setAdapter(mListAdapter);
+ if (isEnableLazy) {
+ isPreload = true;
+ isFirst = true;
+ lazyLoad();
+ } else {
+ mStatusLayout.showLoding();
+ loadDatas();
+ }
+ }
+ }
+
+
+ private void lazyLoad() {
+ if (!isPreload || !isVisible || !isFirst) {
+ return;
+ }
+ mStatusLayout.showLoding();
+ loadDatas();
+ isFirst = false;
+ }
+
+ /**
+ * 懒加载处理
+ *
+ * @param isVisibleToUser
+ */
+ @Override
+ public void setUserVisibleHint(boolean isVisibleToUser) {
+ super.setUserVisibleHint(isVisibleToUser);
+ isEnableLazy = isEnableLazy();//默认不开启懒加载
+ if (!isEnableLazy) return;
+ if (isVisibleToUser) {
+ isVisible = true;
+ lazyLoad();
+ } else {
+ isVisible = false;
+ }
+ }
+
+ /**
+ * 下拉刷新监听
+ */
+ private SwipeRefreshLayout.OnRefreshListener mOnRefreshListener = new SwipeRefreshLayout.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ refreshData();
+ }
+ };
+
+
+ /**
+ * 刷新数据,回到第一页
+ */
+ public void refreshData() {
+ state = Const.PAGE_STATE.STATE_REFRESH;
+ isAutoLoadMore = true;
+ page = getFirstPage();
+ loadDatas();
+ }
+
+ /**
+ * 滑到底部开始加载更多数据
+ */
+ @Override
+ public void loadMore() {
+ if (!isAutoLoadMore) return;
+ state = Const.PAGE_STATE.STATE_LOAD_MORE;
+ loadDatas();
+ }
+
+ /**
+ * 底部加载更多失败,点击重新加载
+ */
+ @Override
+ public void reLoadMore() {
+ isAutoLoadMore = true;
+ loadMore();
+ }
+
+
+ /**
+ * 清空当前列表数据
+ */
+ @Override
+ public void clearListData() {
+ mListData.clear();
+ }
+
+ /**
+ * 自动加载更多
+ */
+ @Override
+ public void autoLoadMore() {
+ mRecyclerView.showLoadMore();
+ page++;
+ isAutoLoadMore = true;
+ }
+
+
+ /**
+ * 底部加载没有更多数据时显示
+ */
+ @Override
+ public void showNoMore() {
+ mRecyclerView.showNoMoreData();
+ isAutoLoadMore = false;
+ }
+
+
+ /**
+ * 数据加载异常时显示
+ */
+ @Override
+ public void showError() {
+ isAutoLoadMore = false;
+ //如果是加载更多出现异常,那么底部就显示点击重新加载;
+ // 否则,就清空数据,显示没有数据
+ if (state == Const.PAGE_STATE.STATE_LOAD_MORE) {
+ mRecyclerView.showLoadMoreError();
+ mListAdapter.notifyAllDatas(mListData, mRecyclerView);
+ } else {
+ mStatusLayout.showError();
+ }
+
+ }
+
+ /**
+ * 没有数据时显示
+ */
+ @Override
+ public void showEmpty() {
+ mStatusLayout.showEmpty();
+ }
+
+
+ /**
+ * 当前请求页
+ *
+ * @return
+ */
+ public int getPage() {
+ return page;
+ }
+
+ @Override
+ public void showLoading(String msg) {
+ if (state == Const.PAGE_STATE.STATE_REFRESH)
+ setRefreshing(true);
+ }
+
+ @Override
+ public void hideLoading() {
+ setRefreshing(false);
+ }
+
+
+ @Override
+ public void showFail(String msg) {
+ ToastUtils.showToast(getActivity(), msg);
+ }
+
+ protected void setRefreshing(final boolean isRefrshing) {
+ mRefreshLayout.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mRefreshLayout.setRefreshing(isRefrshing);
+ }
+ }, 100);
+
+ }
+
+ @Override
+ public int getFirstPage() {
+ return 0;
+ }
+
+ /**
+ * 是否开启懒加载
+ * @return
+ */
+ protected boolean isEnableLazy() {
+ return false;
+ }
+ /**
+ * 是否允许自动加载更多
+ * @return
+ */
+ protected boolean isCanLoadMore(){
+ return false;
+ }
+ @Override
+ protected void getBundle(Bundle bundle) {
+ }
+
+ protected View initHeaderView(){
+ return null;
+ }
+
+ protected abstract void loadDatas();
+
+ protected abstract BaseListAdapter getListAdapter();
+
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseActivity.java b/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseActivity.java
new file mode 100644
index 0000000..081527f
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseActivity.java
@@ -0,0 +1,160 @@
+package com.kdp.wanandroidclient.ui.base;
+import android.app.ProgressDialog;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+import com.kdp.wanandroidclient.R;
+import com.kdp.wanandroidclient.event.RxEvent;
+import io.reactivex.observers.DisposableObserver;
+import io.reactivex.subjects.PublishSubject;
+
+/**
+ * Activity 基类
+ */
+public abstract class BaseActivity extends AppCompatActivity {
+ protected Toolbar mToolbar;
+ protected FrameLayout mContainerLayout;
+ private ProgressDialog loadingDialog = null;
+ private PublishSubject mSubject;
+ private DisposableObserver mDisposableObserver;
+
+ @Override
+ protected void onCreate(Bundle bundle) {
+ if (bundle != null) {
+ //如果系统回收Activity,但是系统却保留了Fragment,当Activity被重新初始化,此时,系统保存的Fragment 的getActivity为空,
+ //所以要移除旧的Fragment,重新初始化新的Fragment
+ String FRAGMENTS_TAG = "android:support:fragments";
+ bundle.remove(FRAGMENTS_TAG);
+ }
+ super.onCreate(bundle);
+
+ setContentView(R.layout.activity_base);
+ Intent intent = getIntent();
+ if (intent != null)
+ getIntent(intent);
+ mToolbar = findViewById(R.id.toolbar);
+ mContainerLayout = findViewById(R.id.frameLayout);
+
+ //初始化ToolBar
+ boolean isToolbar = initToolbar();
+ if (isToolbar) {
+ setSupportActionBar(mToolbar);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
+ //必须要在setSupportActionBar之后,不然不起作用
+ @Override
+ public void onClick(View v) {
+ onNavigationClick();
+ }
+ });
+ } else {
+ mToolbar.setVisibility(View.GONE);
+ }
+ //初始化Content
+ initContent(getLayoutId());
+ //注册事件线
+ mSubject = RxEvent.getInstance().registerEvent(registerEvent());
+ mDisposableObserver = new ReceiveEvent();
+ mSubject.subscribe(mDisposableObserver);
+ }
+
+
+
+
+
+ private class ReceiveEvent extends DisposableObserver{
+ @Override
+ public void onNext(Object o) {
+ receiveEvent(o);
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ }
+
+ @Override
+ public void onComplete() {
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ //注销事件
+ RxEvent.getInstance().unRegisterEvent(registerEvent(), mSubject, mDisposableObserver);
+ }
+
+ private void initContent(int layoutId) {
+ if (layoutId != 0) {
+ View contentView = LayoutInflater.from(this).inflate(layoutId, mContainerLayout, false);
+ mContainerLayout.addView(contentView);
+ initViews();
+ }
+ }
+
+ /**
+ * 显示带消息的进度框
+ *
+ * @param title 提示
+ */
+ protected void showLoadingDialog(String title) {
+ createLoadingDialog();
+ loadingDialog.setMessage(title);
+ if (!loadingDialog.isShowing())
+ loadingDialog.show();
+ }
+
+ /**
+ * 显示进度框
+ */
+ protected void showLoadingDialog() {
+ createLoadingDialog();
+ if (!loadingDialog.isShowing())
+ loadingDialog.show();
+ }
+
+ /**
+ * 创建LodingDialog
+ */
+ private void createLoadingDialog() {
+ if (loadingDialog == null) {
+ loadingDialog = new ProgressDialog(this);
+ loadingDialog.setCancelable(true);
+ loadingDialog.setCanceledOnTouchOutside(false);
+ }
+ }
+
+ /**
+ * 隐藏进度框
+ */
+ protected void hideLoadingDialog() {
+ if (loadingDialog != null && loadingDialog.isShowing()) {
+ loadingDialog.dismiss();
+ }
+ }
+
+ protected void receiveEvent(Object object){ }
+
+ protected String registerEvent(){
+ return null;
+ }
+
+ protected void onNavigationClick() {
+ finish();
+ }
+
+ protected abstract int getLayoutId();
+
+ protected boolean initToolbar(){
+ return false;
+ }
+
+ protected void getIntent(Intent intent){ }
+
+ protected abstract void initViews();
+
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseFragment.java b/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseFragment.java
new file mode 100644
index 0000000..1e8cb0b
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseFragment.java
@@ -0,0 +1,83 @@
+package com.kdp.wanandroidclient.ui.base;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.kdp.wanandroidclient.event.RxEvent;
+
+import io.reactivex.observers.DisposableObserver;
+import io.reactivex.subjects.PublishSubject;
+
+/**
+ * author: 曾文海
+ * date: 2023/5/31
+ */
+
+public abstract class BaseFragment extends Fragment {
+ private PublishSubject mSubject;
+ private DisposableObserver mDisposableObserver;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Bundle bundle = getArguments();
+ if (bundle != null)
+ getBundle(bundle);
+ mDisposableObserver = new ReceiveEvent();
+ //注册事件
+ mSubject = RxEvent.getInstance().registerEvent(registerEvent());
+ mSubject.subscribe(mDisposableObserver);
+ }
+
+ private class ReceiveEvent extends DisposableObserver {
+ @Override
+ public void onNext(Object o) {
+ receiveEvent(o);
+ }
+
+ @Override
+ public void onError(Throwable e) {
+ }
+
+ @Override
+ public void onComplete() {
+ }
+ }
+
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ //注销事件
+ RxEvent.getInstance().unRegisterEvent(registerEvent(), mSubject, mDisposableObserver);
+ }
+
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ View view = null;
+ int layoutId = getLayoutId();
+ if (layoutId != 0) {
+ view = inflater.inflate(getLayoutId(), container, false);
+ initViews(view);
+ }
+ return view;
+ }
+
+ protected abstract void initViews(View view);
+
+ protected abstract int getLayoutId();
+
+ protected void receiveEvent(Object object){}
+
+ protected String registerEvent(){ return null; }
+
+ protected void getBundle(Bundle bundle){}
+
+
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/base/BasePresenterActivity.java b/app/src/main/java/com/kdp/wanandroidclient/ui/base/BasePresenterActivity.java
new file mode 100644
index 0000000..b49f002
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/base/BasePresenterActivity.java
@@ -0,0 +1,104 @@
+package com.kdp.wanandroidclient.ui.base;
+
+import android.content.Intent;
+import android.os.Bundle;
+
+import com.kdp.wanandroidclient.ui.core.presenter.BasePresenter;
+import com.kdp.wanandroidclient.ui.core.view.IView;
+import com.kdp.wanandroidclient.utils.ToastUtils;
+
+/**
+ * 管理Presenter的Activity基类
+
+ */
+
+public abstract class BasePresenterActivity extends BaseActivity implements IView {
+
+ protected P mPresenter;
+
+ @Override
+ protected void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ mPresenter = createPresenter();
+ attachView();
+
+ }
+
+ @Override
+ protected void onNavigationClick() {
+ finish();
+ }
+
+ @Override
+ protected void getIntent(Intent intent) {
+ }
+
+ protected abstract P createPresenter();
+
+ @Override
+ protected void onDestroy() {
+ //接触presenter与View关联
+ detachView();
+ //移除所有请求
+ removeAllDisposable();
+ super.onDestroy();
+ }
+
+ //关联View
+ private void attachView() {
+ if (mPresenter != null) {
+ mPresenter.attachView(this);
+ }
+ }
+
+ private void detachView() {
+ if (mPresenter != null) {
+ mPresenter.detachView();
+ }
+ }
+
+ protected void removeAllDisposable() {
+ if (mPresenter != null) {
+ mPresenter.removeAllDisposable();
+ }
+ }
+
+ @Override
+ protected boolean initToolbar() {
+ return false;
+ }
+
+ @Override
+ protected void initViews() {
+ }
+
+ @Override
+ public void showLoading(String msg) {
+ }
+
+ @Override
+ public void hideLoading() {
+ hideLoadingDialog();
+ }
+
+ @Override
+ public void showFail(String msg) {
+ ToastUtils.showToast(this, msg);
+ }
+ @Override
+ public void showError() {
+ }
+ @Override
+ public void showEmpty() {
+ }
+
+
+ @Override
+ protected void receiveEvent(Object object) {
+ }
+
+ @Override
+ protected String registerEvent() {
+ return null;
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/base/BasePresenterFragment.java b/app/src/main/java/com/kdp/wanandroidclient/ui/base/BasePresenterFragment.java
new file mode 100644
index 0000000..53ac23c
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/base/BasePresenterFragment.java
@@ -0,0 +1,79 @@
+package com.kdp.wanandroidclient.ui.base;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.view.View;
+
+import com.kdp.wanandroidclient.ui.core.presenter.BasePresenter;
+import com.kdp.wanandroidclient.ui.core.view.IView;
+
+/**
+ * author: 曾文海
+ * date: 2023/5/31
+ */
+
+public abstract class BasePresenterFragment
extends BaseFragment implements IView{
+
+ protected P mPresenter;
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mPresenter = createPresenter();
+ //关联View
+ attachView();
+ }
+
+
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ //解除关联
+ detachView();
+ }
+
+ @Override
+ protected void initViews(View view) {
+ }
+
+ @Override
+ protected int getLayoutId() {
+ return 0;
+ }
+
+ private void detachView() {
+ if (mPresenter != null) {
+ mPresenter.detachView();
+ mPresenter.removeAllDisposable();
+ mPresenter = null;
+ }
+ }
+
+ private void attachView() {
+ if (mPresenter != null) {
+ mPresenter.attachView(this);
+ }
+ }
+
+ protected abstract P createPresenter();
+
+ @Override
+ public void showLoading(String msg) {
+ }
+
+ @Override
+ public void hideLoading() {
+ }
+
+ @Override
+ public void showFail(String msg) {
+ }
+
+ @Override
+ public void showError() {
+ }
+
+ @Override
+ public void showEmpty() {
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseTabActivity.java b/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseTabActivity.java
new file mode 100644
index 0000000..a1d6ba8
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseTabActivity.java
@@ -0,0 +1,54 @@
+package com.kdp.wanandroidclient.ui.base;
+
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.design.widget.FloatingActionButton;
+import android.support.design.widget.TabLayout;
+import android.support.v4.app.FragmentPagerAdapter;
+import android.support.v4.view.PagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.view.View;
+
+import com.kdp.wanandroidclient.R;
+import com.kdp.wanandroidclient.common.Const;
+import com.kdp.wanandroidclient.event.Event;
+import com.kdp.wanandroidclient.event.RxEvent;
+
+/***
+ * @author kdp
+ * @date 2023
+ * @description
+ */
+public abstract class BaseTabActivity extends BaseActivity{
+
+ private TabLayout tabLayout;
+ protected ViewPager viewPager;
+ protected FloatingActionButton btn_scroll_top;
+
+
+ @Override
+ protected int getLayoutId() {
+ return R.layout.base_tab_layout;
+ }
+
+ @Override
+ protected void initViews() {
+ tabLayout = findViewById(R.id.tabLayout);
+ viewPager = findViewById(R.id.viewPager);
+ btn_scroll_top = findViewById(R.id.btn_scroll_top);
+ }
+
+ @Override
+ protected void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ FragmentPagerAdapter fragPagerAdapter = createFragPagerAdapter();
+ if (fragPagerAdapter != null){
+ viewPager.setAdapter(fragPagerAdapter);
+ tabLayout.setupWithViewPager(viewPager);
+ }
+ }
+
+
+ protected abstract FragmentPagerAdapter createFragPagerAdapter();
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseTabFragment.java b/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseTabFragment.java
new file mode 100644
index 0000000..deb6787
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/base/BaseTabFragment.java
@@ -0,0 +1,26 @@
+package com.kdp.wanandroidclient.ui.base;
+import android.support.design.widget.TabLayout;
+import android.support.v4.view.ViewPager;
+import android.view.View;
+import com.kdp.wanandroidclient.R;
+import com.kdp.wanandroidclient.ui.core.presenter.BasePresenter;
+
+/***
+ * @author kdp
+ * @date 2023
+ * @description
+ */
+public abstract class BaseTabFragment
extends BasePresenterFragment
{
+ protected TabLayout tabLayout;
+ protected ViewPager viewPager;
+ @Override
+ protected int getLayoutId() {
+ return R.layout.base_tab_layout;
+ }
+
+ @Override
+ protected void initViews(View view) {
+ tabLayout = view.findViewById(R.id.tabLayout);
+ viewPager = view.findViewById(R.id.viewPager);
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChapterContract.java b/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChapterContract.java
new file mode 100644
index 0000000..2aa09e4
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChapterContract.java
@@ -0,0 +1,20 @@
+package com.kdp.wanandroidclient.ui.chapter;
+
+import com.kdp.wanandroidclient.bean.Chapter;
+import com.kdp.wanandroidclient.ui.core.view.IListDataView;
+
+/***
+ * @author kdp
+ * @date 2023
+ * @description
+ */
+public interface ChapterContract {
+
+ interface IChaptersPresenter {
+ void getChapters();
+ }
+
+ interface IChaptersView extends IListDataView{
+
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChapterListContract.java b/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChapterListContract.java
new file mode 100644
index 0000000..977c6e0
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChapterListContract.java
@@ -0,0 +1,23 @@
+package com.kdp.wanandroidclient.ui.chapter;
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.ui.core.view.IPageLoadDataView;
+
+/***
+ * @author kdp
+ * @date 2023
+ * @description
+ */
+public interface ChapterListContract {
+
+ interface IChapterListPresenter{
+ void getChapterList();
+ void collectArticle();
+ void unCollectArticle();
+ }
+
+ interface IChapterListView extends IPageLoadDataView{
+ int getCid();
+ int getArticleId();
+ void collect(boolean isCollect,String result);
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChapterListFragment.java b/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChapterListFragment.java
new file mode 100644
index 0000000..4748c4e
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChapterListFragment.java
@@ -0,0 +1,168 @@
+package com.kdp.wanandroidclient.ui.chapter;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v7.widget.RecyclerView;
+import com.kdp.wanandroidclient.R;
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.common.Const;
+import com.kdp.wanandroidclient.event.Event;
+import com.kdp.wanandroidclient.event.RxEvent;
+import com.kdp.wanandroidclient.inter.OnArticleListItemClickListener;
+import com.kdp.wanandroidclient.manager.UserInfoManager;
+import com.kdp.wanandroidclient.ui.adapter.ArticleListAdapter;
+import com.kdp.wanandroidclient.ui.adapter.BaseListAdapter;
+import com.kdp.wanandroidclient.ui.base.BaseAbListFragment;
+import com.kdp.wanandroidclient.ui.web.WebViewActivity;
+import com.kdp.wanandroidclient.utils.IntentUtils;
+import com.kdp.wanandroidclient.utils.ToastUtils;
+
+import java.util.List;
+
+/***
+ * @author kdp
+ * @date 2023
+ * @description
+ */
+public class ChapterListFragment extends BaseAbListFragment implements ChapterListContract.IChapterListView,OnArticleListItemClickListener {
+
+ private int cid;//公众号id
+ private int id;//文章id
+ private int position;
+
+ public static ChapterListFragment instantiate(int cid){
+ ChapterListFragment instance = new ChapterListFragment();
+ Bundle bundle = new Bundle();
+ bundle.putInt(Const.BUNDLE_KEY.ID,cid);
+ instance.setArguments(bundle);
+ return instance;
+ }
+
+ @Override
+ protected boolean isCanLoadMore() {
+ return true;
+ }
+
+ @Override
+ protected boolean isEnableLazy() {
+ return true;
+ }
+
+ @Override
+ protected void getBundle(Bundle bundle) {
+ if (bundle !=null){
+ cid = bundle.getInt(Const.BUNDLE_KEY.ID,0);
+ }
+ }
+
+ @Override
+ protected void loadDatas() {
+ mPresenter.getChapterList();
+ }
+
+ @Override
+ protected BaseListAdapter getListAdapter() {
+ return new ArticleListAdapter(this,Const.LIST_TYPE.CHAPTER);
+ }
+
+ @Override
+ protected ChapterListPresenter createPresenter() {
+ return new ChapterListPresenter();
+ }
+
+ @Override
+ public void setData(List data) {
+ mListData.addAll(data);
+ }
+
+ @Override
+ public int getFirstPage() {
+ return 1;
+ }
+
+ @Override
+ public int getCid() {
+ return cid;
+ }
+
+ @Override
+ public int getArticleId() {
+ return id;
+ }
+
+ @Override
+ public void collect(boolean isCollect, String result) {
+ notifyItemData(isCollect,result);
+ }
+
+ private void notifyItemData(boolean isCollect, String result) {
+ mListData.get(position).setCollect(isCollect);
+ mListAdapter.notifyItemDataChanged(position, mRecyclerView);
+ ToastUtils.showToast(getActivity(), result);
+ }
+
+
+ @Override
+ public void onDeleteCollectClick(int position, int id, int originId) {
+ }
+
+ @Override
+ public void onCollectClick(int position, int id) {
+ if (!UserInfoManager.isLogin())
+ IntentUtils.goLogin(getActivity());
+ this.id = id;
+ this.position = position;
+ if (mListData.get(this.position).isCollect())
+ mPresenter.unCollectArticle();
+ else
+ mPresenter.collectArticle();
+ }
+
+ @Override
+ public void onItemClick(int position, Article bean) {
+ Intent intent = new Intent(getActivity(), WebViewActivity.class);
+ Bundle bundle = new Bundle();
+ bundle.putSerializable(Const.BUNDLE_KEY.OBJ, bean);
+ bundle.putString(Const.BUNDLE_KEY.TYPE, Const.EVENT_ACTION.CHAPTER_LIST);
+ intent.putExtras(bundle);
+ startActivity(intent);
+ }
+
+ @Override
+ protected void receiveEvent(Object object) {
+ Event mEvent = (Event) object;
+ if (mEvent.type == Event.Type.REFRESH_ITEM) {
+ Article bean = (Article) mEvent.object;
+ for (int i = 0; i < mListData.size(); i++) {
+ if (bean.equals(mListData.get(i))) {
+ position = i;
+ notifyItemData(bean.isCollect(), getString(R.string.collect_success));
+ }
+ }
+ }else if (mEvent.type == Event.Type.SCROLL_TOP && (int)mEvent.object == cid){
+ mRecyclerView.smoothScrollToPosition(0);
+ }
+ else if (mEvent.type == Event.Type.REFRESH_LIST){
+ refreshData();
+ }
+ }
+
+ @Override
+ protected String registerEvent() {
+ return Const.EVENT_ACTION.CHAPTER_LIST;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ mRecyclerView.addOnScrollListener(onScrollListener);
+ }
+
+ private RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+ RxEvent.getInstance().postEvent(Const.EVENT_ACTION.MAIN,new Event(Event.Type.SCALE,dy));
+ }
+ };
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChapterListPresenter.java b/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChapterListPresenter.java
new file mode 100644
index 0000000..aec8a57
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChapterListPresenter.java
@@ -0,0 +1,88 @@
+package com.kdp.wanandroidclient.ui.chapter;
+
+import com.kdp.wanandroidclient.R;
+import com.kdp.wanandroidclient.application.AppContext;
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+import com.kdp.wanandroidclient.net.callback.RxPageListObserver;
+import com.kdp.wanandroidclient.ui.core.model.impl.ChapterListModel;
+import com.kdp.wanandroidclient.ui.core.presenter.BasePresenter;
+
+import java.util.List;
+
+/***
+ * @author kdp
+ * @date 2023
+ * @description
+ */
+public class ChapterListPresenter extends BasePresenter implements ChapterListContract.IChapterListPresenter{
+ private ChapterListModel chapterArticleModel;
+ private ChapterListContract.IChapterListView chapterArticleView;
+
+ public ChapterListPresenter() {
+ this.chapterArticleModel = new ChapterListModel();
+ }
+
+ @Override
+ public void getChapterList() {
+ chapterArticleView = getView();
+ RxPageListObserver rxPageListObserver = new RxPageListObserver(this) {
+ @Override
+ public void onSuccess(List mData) {
+ chapterArticleView.setData(mData);
+ if (chapterArticleView.getData().size() == 0){
+ chapterArticleView.showEmpty();
+ }else {
+ chapterArticleView.showContent();
+ }
+ }
+ @Override
+ public void onFail(int errorCode, String errorMsg) {
+ chapterArticleView.showFail(errorMsg);
+ }
+ };
+ chapterArticleModel.getChapterArticleList(chapterArticleView.getPage(),chapterArticleView.getCid(),rxPageListObserver);
+ addDisposable(rxPageListObserver);
+ }
+
+ @Override
+ public void collectArticle() {
+ RxObserver mCollectRxObserver = new RxObserver(this) {
+ @Override
+ protected void onStart() {
+ }
+ @Override
+ protected void onSuccess(String data) {
+ chapterArticleView.collect(true, AppContext.getContext().getString(R.string.collect_success));
+ }
+ @Override
+ protected void onFail(int errorCode, String errorMsg) {
+ view.showFail(errorMsg);
+ }
+
+ };
+ chapterArticleModel.collectArticle(chapterArticleView.getArticleId(), mCollectRxObserver);
+ addDisposable(mCollectRxObserver);
+ }
+
+ @Override
+ public void unCollectArticle() {
+ RxObserver unCollectRxObserver = new RxObserver(this) {
+
+ @Override
+ protected void onStart() {
+ }
+ @Override
+ protected void onSuccess(String data) {
+ chapterArticleView.collect(false, AppContext.getContext().getString(R.string.uncollect_success));
+ }
+
+ @Override
+ protected void onFail(int errorCode, String errorMsg) {
+ view.showFail(errorMsg);
+ }
+ };
+ chapterArticleModel.unCollectArticle(chapterArticleView.getArticleId(), unCollectRxObserver);
+ addDisposable(unCollectRxObserver);
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChaptersFragment.java b/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChaptersFragment.java
new file mode 100644
index 0000000..5545758
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChaptersFragment.java
@@ -0,0 +1,65 @@
+package com.kdp.wanandroidclient.ui.chapter;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.kdp.wanandroidclient.bean.Chapter;
+import com.kdp.wanandroidclient.common.Const;
+import com.kdp.wanandroidclient.event.Event;
+import com.kdp.wanandroidclient.event.RxEvent;
+import com.kdp.wanandroidclient.ui.adapter.ChaptersFragPagerAdapter;
+import com.kdp.wanandroidclient.ui.base.BaseTabFragment;
+import com.kdp.wanandroidclient.ui.main.MainActivity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/***
+ * @author kdp
+ * @date 2023
+ * @description
+ */
+public class ChaptersFragment extends BaseTabFragment implements ChapterContract.IChaptersView{
+ private List chapterList = new ArrayList<>();
+ @Override
+ protected ChaptersPresenter createPresenter() {
+ return new ChaptersPresenter();
+ }
+
+ @Override
+ public void setData(List data) {
+ chapterList.clear();
+ chapterList.addAll(data);
+ }
+
+ @Override
+ public List getData() {
+ return chapterList;
+ }
+
+ @Override
+ public void showContent() {
+ ChaptersFragPagerAdapter adapter = new ChaptersFragPagerAdapter(getChildFragmentManager(),chapterList);
+ viewPager.setAdapter(adapter);
+ viewPager.setOffscreenPageLimit(chapterList.size());
+ tabLayout.setupWithViewPager(viewPager);
+ }
+
+
+ @Override
+ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ mPresenter.getChapters();
+ }
+
+ public void scrollToTop(){
+ int id = chapterList.get(viewPager.getCurrentItem()).getId();
+ RxEvent.getInstance().postEvent(Const.EVENT_ACTION.CHAPTER_LIST,new Event(Event.Type.SCROLL_TOP,id));
+ }
+
+
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChaptersPresenter.java b/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChaptersPresenter.java
new file mode 100644
index 0000000..e0c991a
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/chapter/ChaptersPresenter.java
@@ -0,0 +1,44 @@
+package com.kdp.wanandroidclient.ui.chapter;
+
+import com.kdp.wanandroidclient.bean.Chapter;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+import com.kdp.wanandroidclient.ui.core.model.impl.ChapterModel;
+import com.kdp.wanandroidclient.ui.core.presenter.BasePresenter;
+
+import java.util.List;
+
+/***
+ * @author kdp
+ * @date 2023
+ * @description
+ */
+public class ChaptersPresenter extends BasePresenter implements ChapterContract.IChaptersPresenter{
+ private ChapterModel chapterModel;
+ private ChapterContract.IChaptersView chaptersView;
+
+ ChaptersPresenter() {
+ this.chapterModel = new ChapterModel();
+ }
+
+ @Override
+ public void getChapters() {
+ chaptersView = getView();
+ RxObserver> rxObserver = new RxObserver>(this) {
+ @Override
+ protected void onSuccess(List data) {
+ chaptersView.setData(data);
+ if (chaptersView.getData().size() == 0) {
+ chaptersView.showEmpty();
+ }else {
+ chaptersView.showContent();
+ }
+ }
+ @Override
+ protected void onFail(int errorCode, String errorMsg) {
+ chaptersView.showFail(errorMsg);
+ }
+ };
+ chapterModel.getChapters(rxObserver);
+ addDisposable(rxObserver);
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IChapterListModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IChapterListModel.java
new file mode 100644
index 0000000..b164d6d
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IChapterListModel.java
@@ -0,0 +1,20 @@
+package com.kdp.wanandroidclient.ui.core.model;
+
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.net.callback.RxPageListObserver;
+
+/***
+ * @author kdp
+ * @date 2023
+ * @description
+ */
+public interface IChapterListModel {
+
+ /**
+ * 获取公众号文章列表
+ * @param page 页码
+ * @param cid 公众号cid
+ * @param rxPageListObserver
+ */
+ void getChapterArticleList(int page, int cid, RxPageListObserver rxPageListObserver);
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IChapterModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IChapterModel.java
new file mode 100644
index 0000000..5057a90
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IChapterModel.java
@@ -0,0 +1,20 @@
+package com.kdp.wanandroidclient.ui.core.model;
+
+import com.kdp.wanandroidclient.bean.Chapter;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+
+import java.util.List;
+
+/***
+ * @author kdp
+ * @date 2019/3/25 16:34
+ * @description
+ */
+public interface IChapterModel {
+
+ /**
+ * 获取公众号
+ * @param rxObserver
+ */
+ void getChapters(RxObserver> rxObserver);
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/ICommonModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/ICommonModel.java
new file mode 100644
index 0000000..560bfaf
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/ICommonModel.java
@@ -0,0 +1,30 @@
+package com.kdp.wanandroidclient.ui.core.model;
+
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+
+/**
+ * 通用业务接口
+ * author: 曾文海
+ * date: 2023/5/31
+ */
+
+public interface ICommonModel {
+
+ /**
+ * 收藏文章
+ *
+ * @param id 文章id
+ * @param callback
+ */
+ void collectArticle(int id, RxObserver callback);
+
+
+ /**
+ * 取消收藏文章
+ *
+ * @param id 文章id
+ * @param callback
+ */
+ void unCollectArticle(int id, RxObserver callback);
+
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IHomeModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IHomeModel.java
new file mode 100644
index 0000000..badad54
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IHomeModel.java
@@ -0,0 +1,41 @@
+package com.kdp.wanandroidclient.ui.core.model;
+
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.bean.Banner;
+import com.kdp.wanandroidclient.bean.BaseBean;
+import com.kdp.wanandroidclient.bean.HomeData;
+import com.kdp.wanandroidclient.bean.PageListData;
+import com.kdp.wanandroidclient.net.callback.RxPageListObserver;
+import java.util.List;
+import io.reactivex.Observable;
+import io.reactivex.functions.Function3;
+import io.reactivex.observers.DisposableObserver;
+
+/**
+ * 首页业务接口
+ * author: 曾文海
+ * date: 2023/5/31
+ */
+
+public interface IHomeModel {
+ /**
+ * 获取首页banner、置顶文章、列表文章
+ * @param page 页码
+ * @param function3
+ * @param rxObserver
+ */
+ void getHomeData(int page, Function3>, BaseBean>, BaseBean>, HomeData> function3, DisposableObserver rxObserver);
+
+ /**
+ * 获取更多文章
+ * @param page 页码
+ * @param rxPageListObserver
+ */
+ void getMoreArticleList(int page,RxPageListObserver rxPageListObserver);
+
+
+ Observable>> getBannerObservable();
+ Observable>> getHomeTopObservable();
+ Observable>> getHomeListObservable(int page);
+
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/ILogonModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/ILogonModel.java
new file mode 100644
index 0000000..c9c1676
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/ILogonModel.java
@@ -0,0 +1,44 @@
+package com.kdp.wanandroidclient.ui.core.model;
+
+import com.kdp.wanandroidclient.bean.User;
+import com.kdp.wanandroidclient.inter.VerifyAccountCallback;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+
+/**
+ * 登录注册业务接口
+
+ */
+
+public interface ILogonModel {
+ /**
+ * 登录
+ *
+ * @param username 用户名
+ * @param password 密码
+ */
+ void login(String username, String password,RxObserver callback);
+
+
+ /**
+ * 注册
+ *
+ * @param username 用户名
+ * @param password 密码
+ */
+ void register(String username, String password,RxObserver callback);
+
+
+ /**
+ * 保存用户信息
+ * @param user 用户
+ */
+ void saveUserInfo(User user);
+
+ /**
+ * 账号密码判空
+ * @param username 用户名
+ * @param password 密码
+ * @return
+ */
+ boolean verifyAccount(String username, String password, VerifyAccountCallback callback);
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IModel.java
new file mode 100644
index 0000000..9b74017
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IModel.java
@@ -0,0 +1,14 @@
+package com.kdp.wanandroidclient.ui.core.model;
+
+import com.kdp.wanandroidclient.api.ApiServer;
+
+
+public interface IModel {
+ /**
+ * 使用RxRetrofit请求数据
+ *
+ * @return
+ */
+ ApiServer doRxRequest();
+
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IProjectCateModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IProjectCateModel.java
new file mode 100644
index 0000000..af8db94
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IProjectCateModel.java
@@ -0,0 +1,20 @@
+package com.kdp.wanandroidclient.ui.core.model;
+
+import com.kdp.wanandroidclient.bean.ProjectCate;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+
+import java.util.List;
+
+/***
+ * @author kdp
+ * @date 2019/3/20 16:52
+ * @description
+ */
+public interface IProjectCateModel {
+
+ /**
+ * 获取项目分类
+ * @param rxObserver
+ */
+ void getProjectCate(RxObserver> rxObserver);
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IProjectModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IProjectModel.java
new file mode 100644
index 0000000..d431c2c
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IProjectModel.java
@@ -0,0 +1,15 @@
+package com.kdp.wanandroidclient.ui.core.model;
+
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.net.callback.RxPageListObserver;
+
+public interface IProjectModel {
+
+ /**
+ * 获取项目列表
+ * @param page 页码
+ * @param cid 项目分类id
+ * @param rxPageListObserver
+ */
+ void getProjectList(int page, int cid, RxPageListObserver rxPageListObserver);
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/ISearchModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/ISearchModel.java
new file mode 100644
index 0000000..24ce72a
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/ISearchModel.java
@@ -0,0 +1,41 @@
+package com.kdp.wanandroidclient.ui.core.model;
+
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.bean.Friend;
+import com.kdp.wanandroidclient.bean.Hotword;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+import com.kdp.wanandroidclient.net.callback.RxPageListObserver;
+
+import java.util.List;
+
+/**
+ * 和搜索相关的业务接口
+ * author: 曾文海
+ * date: 2023/5/31
+ */
+
+public interface ISearchModel {
+
+ /**
+ * 搜索文章
+ *
+ * @param page 页码
+ * @param keyword 关键词
+ * @param rxPageListObserver
+ */
+ void searchArticle(int page, String keyword, RxPageListObserver rxPageListObserver);
+
+ /**
+ * 搜索热词
+ *
+ * @param rxObserver
+ */
+ void getHotWord(RxObserver> rxObserver);
+
+ /**
+ * 常用网站
+ *
+ * @param rxObserver
+ */
+ void getFriend(RxObserver> rxObserver);
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/ITreeListModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/ITreeListModel.java
new file mode 100644
index 0000000..9703ece
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/ITreeListModel.java
@@ -0,0 +1,24 @@
+package com.kdp.wanandroidclient.ui.core.model;
+
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.net.callback.RxPageListObserver;
+
+/**
+ * 知识体系列表业务接口
+ * author: 曾文海
+ * date: 2023/5/31
+ */
+
+public interface ITreeListModel {
+
+
+ /**
+ * 获取知识体系文章列表
+ *
+ * @param page 页码
+ * @param cid 知识体系分类id
+ * @param rxObserver
+ */
+ void getTreeList(int page, int cid, RxPageListObserver rxObserver);
+
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/ITreeModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/ITreeModel.java
new file mode 100644
index 0000000..c0040eb
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/ITreeModel.java
@@ -0,0 +1,21 @@
+package com.kdp.wanandroidclient.ui.core.model;
+
+import com.kdp.wanandroidclient.bean.Tree;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+
+import java.util.List;
+
+/**
+ * 知识体系业务接口
+ * author: 曾文海
+ * date: 2023/5/31
+ */
+
+public interface ITreeModel {
+ /**
+ * 获取知识体系分类
+ *
+ * @param callback
+ */
+ void getTree(RxObserver> callback);
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IUserModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IUserModel.java
new file mode 100644
index 0000000..739f181
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/IUserModel.java
@@ -0,0 +1,30 @@
+package com.kdp.wanandroidclient.ui.core.model;
+
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+import com.kdp.wanandroidclient.net.callback.RxPageListObserver;
+
+/**
+ * 和用户相关的业务接口
+ * author: 曾文海
+ * date: 2023/5/31
+ */
+
+public interface IUserModel {
+ /**
+ * 收藏的文章列表
+ * @param page 页码
+ * @param rxObserver
+ */
+ void getCollectArticleList(int page, RxPageListObserver rxObserver);
+
+
+ /**
+ * 删除收藏
+ *
+ * @param id 收藏列表的文章id
+ * @param originId 首页列表的文章id
+ * @param callback
+ */
+ void deleteCollectArticle(int id, int originId, RxObserver callback);
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/BaseModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/BaseModel.java
new file mode 100644
index 0000000..5aaecb6
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/BaseModel.java
@@ -0,0 +1,14 @@
+package com.kdp.wanandroidclient.ui.core.model.impl;
+
+import com.kdp.wanandroidclient.api.ApiServer;
+import com.kdp.wanandroidclient.net.RxRetrofit;
+import com.kdp.wanandroidclient.ui.core.model.IModel;
+
+
+public class BaseModel implements IModel {
+
+ @Override
+ public ApiServer doRxRequest() {
+ return RxRetrofit.Api();
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/ChapterListModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/ChapterListModel.java
new file mode 100644
index 0000000..066fddf
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/ChapterListModel.java
@@ -0,0 +1,28 @@
+package com.kdp.wanandroidclient.ui.core.model.impl;
+
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.bean.PageListData;
+import com.kdp.wanandroidclient.net.RxSchedulers;
+import com.kdp.wanandroidclient.net.callback.RxPageListObserver;
+import com.kdp.wanandroidclient.ui.core.model.IChapterListModel;
+
+/***
+ * @author kdp
+ * @date 2019/3/27 9:28
+ * @description
+ */
+public class ChapterListModel extends CommonModel implements IChapterListModel {
+ /**
+ * 获取公众号文章列表
+ * @param page 页码
+ * @param cid 公众号cid
+ * @param rxPageListObserver
+ */
+ @Override
+ public void getChapterArticleList(int page, int cid, RxPageListObserver rxPageListObserver) {
+ doRxRequest()
+ .getChapterList(page,cid)
+ .compose(RxSchedulers.>io_main())
+ .subscribe(rxPageListObserver);
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/ChapterModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/ChapterModel.java
new file mode 100644
index 0000000..3feb653
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/ChapterModel.java
@@ -0,0 +1,26 @@
+package com.kdp.wanandroidclient.ui.core.model.impl;
+import com.kdp.wanandroidclient.bean.Chapter;
+import com.kdp.wanandroidclient.net.RxSchedulers;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+import com.kdp.wanandroidclient.ui.core.model.IChapterModel;
+
+import java.util.List;
+
+/***
+ * @author kdp
+ * @date 2019/3/25 16:35
+ * @description
+ */
+public class ChapterModel extends BaseModel implements IChapterModel{
+ /**
+ * 获取公众号
+ * @param rxObserver
+ */
+ @Override
+ public void getChapters(RxObserver> rxObserver) {
+ doRxRequest()
+ .getChapters()
+ .compose(RxSchedulers.>io_main())
+ .subscribe(rxObserver);
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/CommonModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/CommonModel.java
new file mode 100644
index 0000000..60cd20c
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/CommonModel.java
@@ -0,0 +1,41 @@
+package com.kdp.wanandroidclient.ui.core.model.impl;
+
+import com.kdp.wanandroidclient.ui.core.model.ICommonModel;
+import com.kdp.wanandroidclient.net.RxSchedulers;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+
+/**
+ * author: 康栋普
+ * date: 2018/2/26
+ */
+
+public class CommonModel extends BaseModel implements ICommonModel {
+ /**
+ * 收藏
+ * @param id 文章id
+ * @param callback
+ */
+ @Override
+ public void collectArticle(int id, RxObserver callback) {
+ doRxRequest().
+ collectArticle(id)
+ .compose(RxSchedulers.io_main())
+ .subscribe(callback);
+
+ }
+
+ /**
+ * 取消收藏
+ * @param id 文章id
+ * @param callback
+ */
+ @Override
+ public void unCollectArticle(int id, RxObserver callback) {
+ doRxRequest()
+ .unCollectArticle(id)
+ .compose(RxSchedulers.io_main())
+ .subscribe(callback);
+ }
+
+
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/HomeModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/HomeModel.java
new file mode 100644
index 0000000..e751afb
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/HomeModel.java
@@ -0,0 +1,66 @@
+package com.kdp.wanandroidclient.ui.core.model.impl;
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.bean.Banner;
+import com.kdp.wanandroidclient.bean.BaseBean;
+import com.kdp.wanandroidclient.bean.HomeData;
+import com.kdp.wanandroidclient.bean.PageListData;
+import com.kdp.wanandroidclient.net.RxSchedulers;
+import com.kdp.wanandroidclient.net.callback.RxPageListObserver;
+import com.kdp.wanandroidclient.ui.core.model.IHomeModel;
+import java.util.List;
+import io.reactivex.Observable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.functions.Function3;
+import io.reactivex.observers.DisposableObserver;
+import io.reactivex.schedulers.Schedulers;
+
+/**
+ * author: 康栋普
+ * date: 2018/2/22
+ */
+
+public class HomeModel extends CommonModel implements IHomeModel {
+
+ /**
+ * 获取首页banner、置顶文章、列表文章
+ * @param page
+ * @param function3
+ * @param rxObserver
+ */
+ @Override
+ public void getHomeData(int page, Function3>, BaseBean>, BaseBean>, HomeData> function3, DisposableObserver rxObserver) {
+ Observable>> bannerObservable = getBannerObservable();
+ Observable>> homeTopObservable = getHomeTopObservable();
+ Observable>> homeObservable = getHomeListObservable(page);
+ Observable.zip(bannerObservable, homeTopObservable, homeObservable, function3)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(rxObserver);
+ }
+ /**
+ * 获取列表文章
+ * @param page
+ * @param rxPageListObserver
+ */
+ @Override
+ public void getMoreArticleList(int page, RxPageListObserver rxPageListObserver) {
+ doRxRequest().getHomeList(page)
+ .compose(RxSchedulers.>io_main())
+ .subscribe(rxPageListObserver);
+ }
+
+ @Override
+ public Observable>> getBannerObservable() {
+ return doRxRequest().getBanner().subscribeOn(Schedulers.newThread());
+ }
+
+ @Override
+ public Observable>> getHomeTopObservable() {
+ return doRxRequest().getHomeTopList().subscribeOn(Schedulers.newThread());
+ }
+
+ @Override
+ public Observable>> getHomeListObservable(int page) {
+ return doRxRequest().getHomeList(page);
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/LogonModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/LogonModel.java
new file mode 100644
index 0000000..d7268aa
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/LogonModel.java
@@ -0,0 +1,80 @@
+package com.kdp.wanandroidclient.ui.core.model.impl;
+
+import android.text.TextUtils;
+
+import com.kdp.wanandroidclient.R;
+import com.kdp.wanandroidclient.application.AppContext;
+import com.kdp.wanandroidclient.bean.User;
+import com.kdp.wanandroidclient.inter.VerifyAccountCallback;
+import com.kdp.wanandroidclient.manager.UserInfoManager;
+import com.kdp.wanandroidclient.net.RxSchedulers;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+import com.kdp.wanandroidclient.ui.core.model.ILogonModel;
+
+/**
+ * Created by 康栋普 on 2018/2/1.
+ */
+
+public class LogonModel extends BaseModel implements ILogonModel {
+
+ /**
+ * 登录
+ * @param username 用户名
+ * @param password 密码
+ * @param callback
+ */
+ @Override
+ public void login(String username, String password, RxObserver callback) {
+ doRxRequest()
+ .login(username, password)
+ .compose(RxSchedulers.io_main())
+ .subscribe(callback);
+
+
+ }
+
+ /**
+ * 注册
+ * @param username 用户名
+ * @param password 密码
+ * @param callback
+ */
+ @Override
+ public void register(final String username, final String password, RxObserver callback) {
+ doRxRequest()
+ .register(username, password, password)
+ .compose(RxSchedulers.io_main())
+ .subscribe(callback);
+ }
+
+ /**
+ * 保存用户信息
+ * @param user
+ */
+ @Override
+ public void saveUserInfo(User user) {
+ //加密保存用户信息和密钥
+ UserInfoManager.saveUserInfo(user);
+ UserInfoManager.saveIsLogin(true);
+ }
+
+ /**
+ * 账号密码判空
+ * @param username
+ * @param password
+ * @param callback
+ * @return
+ */
+ @Override
+ public boolean verifyAccount(String username, String password, VerifyAccountCallback callback) {
+ if (TextUtils.isEmpty(username)) {
+ callback.onVerifyResult(AppContext.getContext().getString(R.string.username_not_empty));
+ return false;
+ }
+ if (TextUtils.isEmpty(password)) {
+ callback.onVerifyResult(AppContext.getContext().getString(R.string.password_not_empty));
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/ProjectCateModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/ProjectCateModel.java
new file mode 100644
index 0000000..9954c8a
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/ProjectCateModel.java
@@ -0,0 +1,28 @@
+package com.kdp.wanandroidclient.ui.core.model.impl;
+
+import com.kdp.wanandroidclient.bean.ProjectCate;
+import com.kdp.wanandroidclient.net.RxSchedulers;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+import com.kdp.wanandroidclient.ui.core.model.IProjectCateModel;
+
+import java.util.List;
+
+/***
+ * @author kdp
+ * @date 2019/3/20 16:55
+ * @description
+ */
+public class ProjectCateModel extends BaseModel implements IProjectCateModel {
+
+ /**
+ * 获取项目分类
+ * @param rxObserver
+ */
+ @Override
+ public void getProjectCate(RxObserver> rxObserver) {
+ doRxRequest()
+ .getProjectCate()
+ .compose(RxSchedulers.>io_main())
+ .subscribe(rxObserver);
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/ProjectModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/ProjectModel.java
new file mode 100644
index 0000000..ba8e1f8
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/ProjectModel.java
@@ -0,0 +1,23 @@
+package com.kdp.wanandroidclient.ui.core.model.impl;
+
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.bean.PageListData;
+import com.kdp.wanandroidclient.net.RxSchedulers;
+import com.kdp.wanandroidclient.net.callback.RxPageListObserver;
+import com.kdp.wanandroidclient.ui.core.model.IProjectModel;
+
+public class ProjectModel extends CommonModel implements IProjectModel {
+ /**
+ * 获取项目列表
+ * @param page 页码
+ * @param cid 分类id
+ * @param rxPageListObserver
+ */
+ @Override
+ public void getProjectList(int page, int cid, RxPageListObserver rxPageListObserver) {
+ doRxRequest()
+ .getProjectList(page,cid)
+ .compose(RxSchedulers.>io_main())
+ .subscribe(rxPageListObserver);
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/SearchModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/SearchModel.java
new file mode 100644
index 0000000..0367829
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/SearchModel.java
@@ -0,0 +1,58 @@
+package com.kdp.wanandroidclient.ui.core.model.impl;
+
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.bean.Friend;
+import com.kdp.wanandroidclient.bean.Hotword;
+import com.kdp.wanandroidclient.bean.PageListData;
+import com.kdp.wanandroidclient.net.RxSchedulers;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+import com.kdp.wanandroidclient.net.callback.RxPageListObserver;
+import com.kdp.wanandroidclient.ui.core.model.ISearchModel;
+import com.kdp.wanandroidclient.utils.LogUtils;
+
+import java.util.List;
+
+/**
+ * author: 康栋普
+ * date: 2018/4/5
+ */
+
+public class SearchModel extends CommonModel implements ISearchModel {
+ /**
+ * 搜索文章
+ * @param page 页码
+ * @param keyword 关键词
+ * @param rxObserver
+ */
+ @Override
+ public void searchArticle(int page, String keyword, RxPageListObserver rxObserver) {
+ doRxRequest()
+ .search(page, keyword)
+ .compose(RxSchedulers.>io_main())
+ .subscribe(rxObserver);
+ }
+
+ /**
+ * 搜索热词
+ * @param observable
+ */
+ @Override
+ public void getHotWord(RxObserver> observable) {
+ doRxRequest()
+ .getHotKeyword()
+ .compose(RxSchedulers.>io_main())
+ .subscribe(observable);
+ }
+
+ /**
+ * 常用网站
+ * @param rxObserver
+ */
+ @Override
+ public void getFriend(RxObserver> rxObserver) {
+ doRxRequest()
+ .getFriend()
+ .compose(RxSchedulers.>io_main())
+ .subscribe(rxObserver);
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/TreeListModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/TreeListModel.java
new file mode 100644
index 0000000..b35dd88
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/TreeListModel.java
@@ -0,0 +1,30 @@
+package com.kdp.wanandroidclient.ui.core.model.impl;
+
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.bean.PageListData;
+import com.kdp.wanandroidclient.net.RxSchedulers;
+import com.kdp.wanandroidclient.net.callback.RxPageListObserver;
+import com.kdp.wanandroidclient.ui.core.model.ITreeListModel;
+
+/**
+ * author: 康栋普
+ * date: 2018/3/20
+ */
+
+public class TreeListModel extends CommonModel implements ITreeListModel {
+
+ /**
+ * 获取知识体系文章列表
+ * @param page 页码
+ * @param cid 知识体系分类id
+ * @param rxObserver
+ */
+ @Override
+ public void getTreeList(int page,int cid,RxPageListObserver rxObserver) {
+ doRxRequest()
+ .getTreeList(page, cid)
+ .compose(RxSchedulers.>io_main())
+ .subscribe(rxObserver);
+
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/TreeModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/TreeModel.java
new file mode 100644
index 0000000..1c0b727
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/TreeModel.java
@@ -0,0 +1,30 @@
+package com.kdp.wanandroidclient.ui.core.model.impl;
+
+import com.kdp.wanandroidclient.bean.Tree;
+import com.kdp.wanandroidclient.net.RxSchedulers;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+import com.kdp.wanandroidclient.ui.core.model.ITreeModel;
+
+import java.util.List;
+
+/**
+ * author: 康栋普
+ * date: 2018/2/24
+ */
+
+public class TreeModel extends BaseModel implements ITreeModel {
+
+ /**
+ * 获取知识体系分类
+ * @param callback
+ */
+ @Override
+ public void getTree(RxObserver> callback) {
+ doRxRequest()
+ .getTree()
+ .compose(RxSchedulers.>io_main())
+ .subscribe(callback);
+ }
+
+
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/UserModel.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/UserModel.java
new file mode 100644
index 0000000..818d598
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/model/impl/UserModel.java
@@ -0,0 +1,42 @@
+package com.kdp.wanandroidclient.ui.core.model.impl;
+
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.bean.PageListData;
+import com.kdp.wanandroidclient.net.RxSchedulers;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+import com.kdp.wanandroidclient.net.callback.RxPageListObserver;
+import com.kdp.wanandroidclient.ui.core.model.IUserModel;
+
+/**
+ * author: 康栋普
+ * date: 2018/3/21
+ */
+
+public class UserModel extends CommonModel implements IUserModel {
+ /**
+ * 收藏的文章列表
+ * @param page 页码
+ * @param rxObserver
+ */
+ @Override
+ public void getCollectArticleList(int page, RxPageListObserver rxObserver) {
+ doRxRequest()
+ .getCollectArticleList(page)
+ .compose(RxSchedulers.>io_main())
+ .subscribe(rxObserver);
+ }
+
+ /**
+ * 删除收藏
+ * @param id 收藏列表的文章id
+ * @param originId 首页列表的文章id
+ * @param callback
+ */
+ @Override
+ public void deleteCollectArticle(int id, int originId, RxObserver callback) {
+ doRxRequest()
+ .deleteCollectArticle(id, originId)
+ .compose(RxSchedulers.io_main())
+ .subscribe(callback);
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/presenter/BasePresenter.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/presenter/BasePresenter.java
new file mode 100644
index 0000000..27c14f3
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/presenter/BasePresenter.java
@@ -0,0 +1,66 @@
+package com.kdp.wanandroidclient.ui.core.presenter;
+
+import com.kdp.wanandroidclient.ui.core.view.IView;
+
+import io.reactivex.disposables.CompositeDisposable;
+import io.reactivex.disposables.Disposable;
+
+/**
+ * 基类Presenter,用来处理view和请求
+
+ */
+
+public class BasePresenter implements IPresenter {
+ private V view;
+ //用来存放Disposable的容器
+ private CompositeDisposable mCompositeDisposable;
+
+ //绑定View
+ @Override
+ public void attachView(V view) {
+ this.view = view;
+ }
+
+ //解除View绑定
+ @Override
+ public void detachView() {
+ this.view = null;
+ }
+
+ //获取绑定的View
+ @Override
+ public V getView() {
+ checkAttachView();
+ return view;
+ }
+
+ //检查View是否存在
+ @Override
+ public void checkAttachView() {
+ if (view == null)
+ throw new RuntimeException("You have no binding this view");
+ }
+
+ //添加指定的请求
+ @Override
+ public void addDisposable(Disposable disposable) {
+ if (mCompositeDisposable == null)
+ mCompositeDisposable = new CompositeDisposable();
+ mCompositeDisposable.add(disposable);
+ }
+
+ //移除指定的请求
+ @Override
+ public void removeDisposable(Disposable disposable) {
+ if (mCompositeDisposable != null)
+ mCompositeDisposable.remove(disposable);
+ }
+
+ //取消所有的请求Tag
+ @Override
+ public void removeAllDisposable() {
+ if (mCompositeDisposable != null)
+ mCompositeDisposable.clear();
+ }
+
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/presenter/IPresenter.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/presenter/IPresenter.java
new file mode 100644
index 0000000..bd8efea
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/presenter/IPresenter.java
@@ -0,0 +1,31 @@
+package com.kdp.wanandroidclient.ui.core.presenter;
+
+import com.kdp.wanandroidclient.ui.core.view.IView;
+
+import io.reactivex.disposables.Disposable;
+
+/**
+ * Presenter接口类
+
+ */
+
+public interface IPresenter {
+
+ //绑定View
+ void attachView(V view);
+
+ //解除View绑定
+ void detachView();
+
+ //检查View是否存在
+ void checkAttachView();
+
+ V getView();
+
+ //添加指定的请求
+ void addDisposable(Disposable disposable);
+ //移除指定的请求
+ void removeDisposable(Disposable disposable);
+ //取消所有请求
+ void removeAllDisposable();
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/view/IListDataView.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/view/IListDataView.java
new file mode 100644
index 0000000..4453088
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/view/IListDataView.java
@@ -0,0 +1,17 @@
+package com.kdp.wanandroidclient.ui.core.view;
+
+import java.util.List;
+
+/***
+ * @author kdp
+ * @date 2019/3/20 13:03
+ * @description
+ */
+public interface IListDataView extends IView{
+
+ void setData(List data);
+
+ List getData();
+
+ void showContent(); //显示内容
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/view/IPageLoadDataView.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/view/IPageLoadDataView.java
new file mode 100644
index 0000000..35342fe
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/view/IPageLoadDataView.java
@@ -0,0 +1,17 @@
+package com.kdp.wanandroidclient.ui.core.view;
+
+
+/**
+ * 列表View
+ * author: 曾文海
+ * date: 2023/5/31
+ */
+
+public interface IPageLoadDataView extends IListDataView{
+
+ int getFirstPage();
+ int getPage();
+ void autoLoadMore();//自动加载
+ void clearListData();//清空所有数据
+ void showNoMore();//没有更多数据
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/core/view/IView.java b/app/src/main/java/com/kdp/wanandroidclient/ui/core/view/IView.java
new file mode 100644
index 0000000..70ba500
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/core/view/IView.java
@@ -0,0 +1,41 @@
+package com.kdp.wanandroidclient.ui.core.view;
+
+/**
+ * view基类
+
+ */
+
+public interface IView{
+
+
+ /**
+ * 显示进度条
+ *
+ */
+ void showLoading(String msg);
+
+ /**
+ * 隐藏进度条
+ */
+ void hideLoading();
+
+ /**
+ * 失败
+ *
+ * @param msg
+ */
+ void showFail(String msg);
+
+ /**
+ * 错误
+ */
+ void showError();
+
+ /**
+ * 没有数据
+ */
+ void showEmpty();//没有数据
+
+
+
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/home/HomeContract.java b/app/src/main/java/com/kdp/wanandroidclient/ui/home/HomeContract.java
new file mode 100644
index 0000000..2a34a8b
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/home/HomeContract.java
@@ -0,0 +1,30 @@
+package com.kdp.wanandroidclient.ui.home;
+
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.bean.Banner;
+import com.kdp.wanandroidclient.ui.core.view.IPageLoadDataView;
+
+import java.util.List;
+
+/**
+ * Home协约类
+ * author: 曾文海
+ * date: 2023/5/31
+ */
+
+public interface HomeContract {
+ interface IHomePresenter {
+ void getHomeData();
+ void getMoreArticleList();
+
+ void collectArticle();
+
+ void unCollectArticle();
+ }
+
+ interface IHomeView extends IPageLoadDataView {
+ int getArticleId();
+ void setBannerData(List banner);
+ void collect(boolean isCollect,String result);
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/home/HomeFragment.java b/app/src/main/java/com/kdp/wanandroidclient/ui/home/HomeFragment.java
new file mode 100644
index 0000000..7635c24
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/home/HomeFragment.java
@@ -0,0 +1,224 @@
+package com.kdp.wanandroidclient.ui.home;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.kdp.wanandroidclient.R;
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.bean.Banner;
+import com.kdp.wanandroidclient.common.Const;
+import com.kdp.wanandroidclient.event.Event;
+import com.kdp.wanandroidclient.event.RxEvent;
+import com.kdp.wanandroidclient.inter.OnArticleListItemClickListener;
+import com.kdp.wanandroidclient.manager.UserInfoManager;
+import com.kdp.wanandroidclient.ui.adapter.ArticleListAdapter;
+import com.kdp.wanandroidclient.ui.adapter.BannerAdapter;
+import com.kdp.wanandroidclient.ui.adapter.BaseListAdapter;
+import com.kdp.wanandroidclient.ui.base.BaseAbListFragment;
+import com.kdp.wanandroidclient.ui.main.MainActivity;
+import com.kdp.wanandroidclient.ui.tree.TreeActivity;
+import com.kdp.wanandroidclient.ui.web.WebViewActivity;
+import com.kdp.wanandroidclient.utils.IntentUtils;
+import com.kdp.wanandroidclient.utils.ToastUtils;
+import com.kdp.wanandroidclient.widget.BannerViewPager;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * 首页文章
+ * author: 曾文海
+ * date: 2023/5/31
+ */
+
+public class HomeFragment extends BaseAbListFragment implements HomeContract.IHomeView, OnArticleListItemClickListener {
+ private int id;//文章id
+ private int position;
+ private List mBannerList = new ArrayList<>();
+ private BannerViewPager mViewPager;
+ private BannerAdapter mBannerAdapter;
+
+ @Override
+ protected HomePresenter createPresenter() {
+ return new HomePresenter();
+ }
+
+ @Override
+ protected boolean isCanLoadMore() {
+ return true;
+ }
+
+ //初始化HeaderView
+ @Override
+ protected View initHeaderView() {
+ View headerView = LayoutInflater.from(getActivity()).inflate(R.layout.main_header_banner, mRecyclerView, false);
+ mViewPager = headerView.findViewById(R.id.viewPager);
+ return headerView;
+ }
+
+
+ //设置Banner选中item
+ private void setCurrentItem(final int position) {
+ mViewPager.setCurrentItem(position, false);
+ }
+
+ //加载列表数据
+ @Override
+ protected void loadDatas() {
+ if (page == getFirstPage()){
+ //刷新
+ mPresenter.getHomeData();
+ }else {
+ //加载更多
+ mPresenter.getMoreArticleList();
+ }
+ }
+
+ @Override
+ protected BaseListAdapter getListAdapter() {
+ return new ArticleListAdapter(this, Const.LIST_TYPE.HOME);
+ }
+
+ //Banner数据
+ @Override
+ public void setBannerData(List banner) {
+ mBannerList.clear();
+ mBannerList.addAll(banner);
+ }
+
+ //列表数据
+ @Override
+ public void setData(List data) {
+ mListData.addAll(data);
+ }
+
+ //显示内容
+ @Override
+ public void showContent() {
+ notifyDatas();
+ super.showContent();
+ }
+
+ //刷新所有数据
+ public void notifyDatas() {
+ if (mBannerAdapter == null) {
+ mBannerAdapter = new BannerAdapter(mBannerList);
+ mViewPager.setAdapter(mBannerAdapter);
+ mViewPager.setOffscreenPageLimit(mBannerList.size());
+ setCurrentItem(1000 * mBannerList.size());
+ }
+ mBannerAdapter.notifyDatas(mBannerList);
+ }
+
+
+ //收藏结果
+ @Override
+ public void collect(boolean isCollect, String result) {
+ notifyItemData(isCollect, result);
+ }
+
+ //刷新单条Item
+ private void notifyItemData(boolean isCollect, String result) {
+ mListData.get(position).setCollect(isCollect);
+ position++;
+ mListAdapter.notifyItemDataChanged(position, mRecyclerView);
+ ToastUtils.showToast(getActivity(), result);
+ }
+
+ //文章id
+ @Override
+ public int getArticleId() {
+ return id;
+ }
+
+ //进入详情
+ @Override
+ public void onItemClick(int position,Article bean) {
+ Intent intent = new Intent(getActivity(), WebViewActivity.class);
+ Bundle bundle = new Bundle();
+ bundle.putSerializable(Const.BUNDLE_KEY.OBJ, bean);
+ bundle.putString(Const.BUNDLE_KEY.TYPE, Const.EVENT_ACTION.HOME);
+ intent.putExtras(bundle);
+ startActivity(intent);
+ }
+
+ @Override
+ public void onDeleteCollectClick(int position, int id, int originId) {
+ }
+
+ //收藏click
+ @Override
+ public void onCollectClick(int position, int id) {
+ if (!UserInfoManager.isLogin())
+ IntentUtils.goLogin(getActivity());
+ this.position = position;
+ this.id = id;
+ if (mListData.get(this.position).isCollect())
+ mPresenter.unCollectArticle();
+ else
+ mPresenter.collectArticle();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mViewPager.start();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mViewPager.stop();
+ }
+
+ @Override
+ public void onHiddenChanged(boolean hidden) {
+ if (hidden) {
+ mViewPager.stop();
+ } else {
+ mViewPager.start();
+ }
+ }
+
+ @Override
+ protected void receiveEvent(Object object) {
+ Event mEvent = (Event) object;
+ if (mEvent.type == Event.Type.REFRESH_ITEM) {
+ Article bean = (Article) mEvent.object;
+ for (int i = 0; i < mListData.size(); i++) {
+ if (bean.equals(mListData.get(i))) {
+ position = i;
+ notifyItemData(bean.isCollect(), getString(R.string.collect_success));
+ }
+ }
+ }else if (mEvent.type == Event.Type.SCROLL_TOP){
+ mRecyclerView.smoothScrollToPosition(0);
+ }else if (mEvent.type == Event.Type.REFRESH_LIST){
+ refreshData();
+ }
+ }
+
+ @Override
+ protected String registerEvent() {
+ return Const.EVENT_ACTION.HOME;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ mRecyclerView.addOnScrollListener(onScrollListener);
+ }
+
+ private RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+ RxEvent.getInstance().postEvent(Const.EVENT_ACTION.MAIN,new Event(Event.Type.SCALE,dy));
+ }
+ };
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/home/HomePresenter.java b/app/src/main/java/com/kdp/wanandroidclient/ui/home/HomePresenter.java
new file mode 100644
index 0000000..6445eaf
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/home/HomePresenter.java
@@ -0,0 +1,141 @@
+package com.kdp.wanandroidclient.ui.home;
+import com.kdp.wanandroidclient.R;
+import com.kdp.wanandroidclient.application.AppContext;
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.bean.Banner;
+import com.kdp.wanandroidclient.bean.BaseBean;
+import com.kdp.wanandroidclient.bean.HomeData;
+import com.kdp.wanandroidclient.bean.PageListData;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+import com.kdp.wanandroidclient.net.callback.RxPageListObserver;
+import com.kdp.wanandroidclient.net.callback.RxZipObserver;
+import com.kdp.wanandroidclient.ui.core.model.impl.HomeModel;
+import com.kdp.wanandroidclient.ui.core.presenter.BasePresenter;
+import java.util.List;
+import io.reactivex.functions.Function3;
+
+/**
+ * Home Presenter
+ * author: 曾文海
+ * date: 2023/5/31
+ */
+
+public class HomePresenter extends BasePresenter implements HomeContract.IHomePresenter {
+ private HomeModel homeModel;
+ private HomeContract.IHomeView homeView;
+
+ HomePresenter() {
+ this.homeModel = new HomeModel();
+ }
+
+ /**
+ * 获取首页Banner、置顶文章、列表文章
+ */
+ @Override
+ public void getHomeData() {
+ homeView = getView();
+ Function3>, BaseBean>, BaseBean>, HomeData> function3 = new Function3>, BaseBean>, BaseBean>, HomeData>() {
+ @Override
+ public HomeData apply(BaseBean> banner, BaseBean> homeTop, BaseBean> home) throws Exception {
+ HomeData homeData = new HomeData();
+ homeData.setBanner(banner);
+ for (Article bean : homeTop.data){
+ //置顶
+ bean.setTop(true);
+ }
+ homeData.setHomeTop(homeTop);
+ homeData.setHome(home);
+ return homeData;
+ }
+ };
+
+
+ RxZipObserver rxZipObserver = new RxZipObserver(this) {
+ @Override
+ public void onNext(HomeData homeData) {
+ homeView.setBannerData(homeData.getBanner().data);
+ List list = homeData.getHome().data.getDatas();
+ list.addAll(0,homeData.getHomeTop().data);
+ homeView.clearListData();
+ homeView.autoLoadMore();
+ homeView.setData(list);
+ if (homeView.getData().size() == 0) {
+ homeView.showEmpty();
+ }else {
+ homeView.showContent();
+ }
+ }
+ };
+ homeModel.getHomeData(homeView.getPage(),function3, rxZipObserver);
+ addDisposable(rxZipObserver);
+ }
+
+ /**
+ * 加载更多,获取更多文章
+ */
+ @Override
+ public void getMoreArticleList() {
+ homeView = getView();
+ RxPageListObserver rxPageListObserver = new RxPageListObserver(this) {
+ @Override
+ public void onSuccess(List homeList) {
+ homeView.getData().addAll(homeList);
+ homeView.showContent();
+ }
+ @Override
+ public void onFail(int errorCode, String errorMsg) {
+ homeView.showFail(errorMsg);
+ }
+ };
+ homeModel.getMoreArticleList(homeView.getPage(),rxPageListObserver);
+ addDisposable(rxPageListObserver);
+ }
+
+ /**
+ * 收藏
+ */
+ @Override
+ public void collectArticle() {
+ RxObserver mCollectRxObserver = new RxObserver(this) {
+ @Override
+ protected void onStart() {
+ }
+ @Override
+ protected void onSuccess(String data) {
+ homeView.collect(true, AppContext.getContext().getString(R.string.collect_success));
+ }
+ @Override
+ protected void onFail(int errorCode, String errorMsg) {
+ view.showFail(errorMsg);
+ }
+
+ };
+ homeModel.collectArticle(homeView.getArticleId(), mCollectRxObserver);
+ addDisposable(mCollectRxObserver);
+ }
+
+ /**
+ * 取消收藏
+ */
+ @Override
+ public void unCollectArticle() {
+ RxObserver unCollectRxObserver = new RxObserver(this) {
+
+ @Override
+ protected void onStart() {
+ }
+ @Override
+ protected void onSuccess(String data) {
+ homeView.collect(false, AppContext.getContext().getString(R.string.uncollect_success));
+ }
+
+ @Override
+ protected void onFail(int errorCode, String errorMsg) {
+ view.showFail(errorMsg);
+ }
+ };
+ homeModel.unCollectArticle(homeView.getArticleId(), unCollectRxObserver);
+ addDisposable(unCollectRxObserver);
+ }
+
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/logon/LogonActivity.java b/app/src/main/java/com/kdp/wanandroidclient/ui/logon/LogonActivity.java
new file mode 100644
index 0000000..1294444
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/logon/LogonActivity.java
@@ -0,0 +1,82 @@
+package com.kdp.wanandroidclient.ui.logon;
+
+import android.os.Bundle;
+import android.view.View;
+import android.widget.EditText;
+
+import com.kdp.wanandroidclient.R;
+import com.kdp.wanandroidclient.application.AppContext;
+import com.kdp.wanandroidclient.common.Const;
+import com.kdp.wanandroidclient.event.Event;
+import com.kdp.wanandroidclient.event.RxEvent;
+import com.kdp.wanandroidclient.ui.base.BasePresenterActivity;
+import com.kdp.wanandroidclient.utils.LightStatusbarUtils;
+import com.kdp.wanandroidclient.utils.ToastUtils;
+
+/**
+ * 登录、注册
+
+ */
+
+public class LogonActivity extends BasePresenterActivity implements LogonContract.ILoginRegisterView {
+ private EditText et_username, et_password;
+
+ @Override
+ public String getUserName() {
+ return et_username.getText().toString().trim();
+ }
+
+ @Override
+ public String getPassWord() {
+ return et_password.getText().toString().trim();
+ }
+
+ @Override
+ public void showResult(String msg) {
+ ToastUtils.showToast(AppContext.getContext(), msg);
+ RxEvent.getInstance().postEvent(Const.EVENT_ACTION.HOME, new Event(Event.Type.REFRESH_LIST));
+ finish();
+ }
+
+ @Override
+ public void showLoading(String msg) {
+ showLoadingDialog(msg);
+ }
+
+ @Override
+ protected LogonPresenter createPresenter() {
+ return new LogonPresenter();
+ }
+
+ @Override
+ protected int getLayoutId() {
+ return R.layout.activity_login;
+ }
+
+
+ @Override
+ protected void initViews() {
+ et_username = findViewById(R.id.et_username);
+ et_password = findViewById(R.id.et_password);
+ findViewById(R.id.bt_login).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mPresenter.login();
+ }
+ });
+ findViewById(R.id.bt_register).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mPresenter.register();
+ }
+ });
+ }
+
+ @Override
+ protected void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ LightStatusbarUtils.setLightStatusBar(this, true);
+ }
+
+
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/logon/LogonContract.java b/app/src/main/java/com/kdp/wanandroidclient/ui/logon/LogonContract.java
new file mode 100644
index 0000000..0ab528c
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/logon/LogonContract.java
@@ -0,0 +1,41 @@
+package com.kdp.wanandroidclient.ui.logon;
+
+import com.kdp.wanandroidclient.ui.core.view.IView;
+
+/**
+ * 登录、注册协约类
+ * author: 曾文海
+ * date: 2023/5/31
+ */
+
+public interface LogonContract {
+
+ interface IUserPresenter {
+ void login();
+
+ void register();
+ }
+
+
+ interface ILoginRegisterView extends IView {
+
+ /**
+ * 获取用户名
+ *
+ * @return
+ */
+ String getUserName();
+
+ /**
+ * 获取密码
+ *
+ * @return
+ */
+ String getPassWord();
+
+ /**
+ * 登录或注册Result
+ */
+ void showResult(String msg);
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/logon/LogonPresenter.java b/app/src/main/java/com/kdp/wanandroidclient/ui/logon/LogonPresenter.java
new file mode 100644
index 0000000..6f1afb7
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/logon/LogonPresenter.java
@@ -0,0 +1,97 @@
+package com.kdp.wanandroidclient.ui.logon;
+
+import com.kdp.wanandroidclient.R;
+import com.kdp.wanandroidclient.application.AppContext;
+import com.kdp.wanandroidclient.bean.User;
+import com.kdp.wanandroidclient.inter.VerifyAccountCallback;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+import com.kdp.wanandroidclient.ui.core.model.impl.LogonModel;
+import com.kdp.wanandroidclient.ui.core.presenter.BasePresenter;
+
+/**
+ * 登录、注册Presenter
+
+ */
+
+public class LogonPresenter extends BasePresenter implements LogonContract.IUserPresenter {
+
+ private String username, password;
+ private LogonModel logonModel;
+ private LogonContract.ILoginRegisterView mLogonView;
+
+ public LogonPresenter() {
+ this.logonModel = new LogonModel();
+ }
+
+ /**
+ * 登录
+ */
+ @Override
+ public void login() {
+ if(!verifyAccount()) return;
+ RxObserver mLoginRxObserver = new RxObserver(this) {
+ @Override
+ protected void onStart() {
+ mLogonView.showLoading(AppContext.getContext().getString(R.string.isLoging));
+ }
+
+ @Override
+ protected void onSuccess(User userBean) {
+ userBean.setPassword(password);
+ logonModel.saveUserInfo(userBean);
+ mLogonView.showResult(AppContext.getContext().getString(R.string.login_success));
+ }
+
+ @Override
+ protected void onFail(int errorCode, String errorMsg) {
+ mLogonView.showFail(errorMsg);
+ }
+ };
+ logonModel.login(username, password, mLoginRxObserver);
+ addDisposable(mLoginRxObserver);
+ }
+
+ /**
+ * 注册
+ */
+ @Override
+ public void register() {
+ if (!verifyAccount()) return;
+ RxObserver mRegisterRxObserver = new RxObserver(this) {
+ @Override
+ protected void onStart() {
+ mLogonView.showLoading(AppContext.getContext().getString(R.string.isRegistering));
+ }
+
+ @Override
+ protected void onSuccess(String data) {
+ mLogonView.showResult(AppContext.getContext().getString(R.string.register_success));
+ }
+
+ @Override
+ protected void onFail(int errorCode, String errorMsg) {
+ mLogonView.showFail(errorMsg);
+ }
+ };
+ logonModel.register(username, password, mRegisterRxObserver);
+ addDisposable(mRegisterRxObserver);
+ }
+
+ private VerifyAccountCallback mVerifyAccountCallback = new VerifyAccountCallback() {
+ @Override
+ public void onVerifyResult(String msg) {
+ mLogonView.showFail(msg);
+ }
+ };
+
+ /**
+ * 帐号验证
+ */
+ private boolean verifyAccount() {
+ mLogonView = getView();
+ username = mLogonView.getUserName();
+ password = mLogonView.getPassWord();
+ return logonModel.verifyAccount(username, password, mVerifyAccountCallback);
+ }
+
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/main/MainActivity.java b/app/src/main/java/com/kdp/wanandroidclient/ui/main/MainActivity.java
new file mode 100644
index 0000000..59c8bce
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/main/MainActivity.java
@@ -0,0 +1,333 @@
+package com.kdp.wanandroidclient.ui.main;
+
+import android.animation.Animator;
+import android.annotation.SuppressLint;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.design.widget.FloatingActionButton;
+import android.support.design.widget.NavigationView;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v4.view.animation.LinearOutSlowInInterpolator;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v7.app.ActionBarDrawerToggle;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewPropertyAnimator;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.kdp.wanandroidclient.R;
+import com.kdp.wanandroidclient.application.AppContext;
+import com.kdp.wanandroidclient.bean.User;
+import com.kdp.wanandroidclient.common.Const;
+import com.kdp.wanandroidclient.event.Event;
+import com.kdp.wanandroidclient.event.RxEvent;
+import com.kdp.wanandroidclient.manager.ImageLoaderManager;
+import com.kdp.wanandroidclient.manager.UserInfoManager;
+import com.kdp.wanandroidclient.ui.base.BaseActivity;
+import com.kdp.wanandroidclient.ui.chapter.ChaptersFragment;
+import com.kdp.wanandroidclient.ui.home.HomeFragment;
+import com.kdp.wanandroidclient.ui.project.ProjectFragment;
+import com.kdp.wanandroidclient.ui.tree.TreeFragment;
+import com.kdp.wanandroidclient.ui.user.AboutUsActivity;
+import com.kdp.wanandroidclient.ui.user.CollectArticleActivity;
+import com.kdp.wanandroidclient.utils.IntentUtils;
+import com.kdp.wanandroidclient.utils.PreUtils;
+import com.kdp.wanandroidclient.utils.ToastUtils;
+import com.kdp.wanandroidclient.utils.ViewAnimatorHelper;
+
+/**
+ * 管理首页Tab的Activity
+ */
+public class MainActivity extends BaseActivity implements View.OnClickListener {
+ private DrawerLayout mDrawerLayout;
+ private NavigationView mNavigationView;
+ private FloatingActionButton btn_scroll_top;
+ private TextView mNameView;
+ private ImageView mAvatarView;
+ private Button[] btns;
+ private Fragment[] fragments;
+ private int currentPosition;
+ private int index;
+ private ViewAnimatorHelper viewAnimatorHelper;
+
+
+ @Override
+ protected int getLayoutId() {
+ return R.layout.activity_main;
+ }
+
+ @Override
+ protected boolean initToolbar() {
+ mToolbar.setTitle(R.string.app_name);
+ mToolbar.setNavigationIcon(R.drawable.ic_menu_white_24dp);
+ return true;
+ }
+
+
+ public void setCurrentTitle() {
+ if (currentPosition == 0)
+ mToolbar.setTitle(R.string.app_name);
+ else if (currentPosition == 1)
+ mToolbar.setTitle(R.string.system);
+ else if(currentPosition == 2)
+ mToolbar.setTitle(R.string.chapter);
+ else if (currentPosition == 3)
+ mToolbar.setTitle(R.string.project);
+
+ }
+
+ @Override
+ protected void initViews() {
+ mDrawerLayout = findViewById(R.id.drawerLayout);
+ mNavigationView = findViewById(R.id.navigation_view);
+ btn_scroll_top = findViewById(R.id.btn_scroll_top);
+ btns = new Button[4];
+ btns[0] = findViewById(R.id.btn_main);
+ btns[1] = findViewById(R.id.btn_system);
+ btns[2] = findViewById(R.id.btn_chapter);
+ btns[3] = findViewById(R.id.btn_project);
+ btns[0].setSelected(true);
+
+ for (int i = 0; i < btns.length; i++) {
+ btns[i].setOnClickListener(this);
+ if (i != currentPosition) {
+ btns[i].setScaleX(0.9f);
+ btns[i].setScaleY(0.9f);
+ }
+ }
+
+ btn_scroll_top.setOnClickListener(onScrollTopListener);
+ }
+
+ private View.OnClickListener onScrollTopListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String action="";
+ switch (currentPosition) {
+ case 0:
+ action = Const.EVENT_ACTION.HOME;
+ break;
+ case 1:
+ action = Const.EVENT_ACTION.SYSTEM;
+ break;
+ case 2:
+ ((ChaptersFragment)fragments[2]).scrollToTop();
+ return;
+ case 3:
+ ((ProjectFragment)fragments[3]).scrollToTop();
+ return;
+
+ }
+ RxEvent.getInstance().postEvent(action,new Event(Event.Type.SCROLL_TOP));
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ //设置Home旋转开关按钮
+ ActionBarDrawerToggle mToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolbar,
+ R.string.navigation_drawer_open,
+ R.string.navigation_drawer_close);
+ mToggle.syncState();
+ mDrawerLayout.addDrawerListener(mToggle);
+ mNavigationView.setItemIconTintList(null);
+ mNavigationView.setNavigationItemSelectedListener(onNavigationItemSelectedListener);
+ //侧滑菜单
+ initNavigationHeaderView();
+ initFragments();
+ viewAnimatorHelper = new ViewAnimatorHelper();
+ viewAnimatorHelper.bindView(btn_scroll_top);
+ }
+
+
+
+ private void initNavigationHeaderView() {
+ View mHeaderView = mNavigationView.getHeaderView(0);
+ mAvatarView = mHeaderView.findViewById(R.id.img_avatar);
+ mNameView = mHeaderView.findViewById(R.id.tv_name);
+ }
+
+ private void setUserData() {
+ if (UserInfoManager.isLogin()) {
+ User user = UserInfoManager.getUserInfo();
+ if (user != null) {
+ mNameView.setText(user.getUsername());
+ ImageLoaderManager.displayImage(user.getIcon(), mAvatarView, Const.IMAGE_LOADER.HEAD_IMG);
+ }
+ } else {
+ mNameView.setText("未登录");
+ }
+ }
+
+
+ private void initFragments() {
+ fragments = new Fragment[]{new HomeFragment(), new TreeFragment(),new ChaptersFragment(),new ProjectFragment()};
+ FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+ ft.add(R.id.container, fragments[0]).show(fragments[0]).commitAllowingStateLoss();
+ }
+
+
+ //设置侧滑item click
+ private NavigationView.OnNavigationItemSelectedListener onNavigationItemSelectedListener = new NavigationView.OnNavigationItemSelectedListener() {
+ @Override
+ public boolean onNavigationItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_favorite_article: {
+ if (!UserInfoManager.isLogin()) {
+ IntentUtils.goLogin(MainActivity.this);
+ } else {
+ startActivity(new Intent(MainActivity.this, CollectArticleActivity.class));
+ }
+ }
+ break;
+ case R.id.menu_about:
+ startActivity(new Intent(MainActivity.this, AboutUsActivity.class));
+ break;
+ case R.id.menu_exit:
+ exitToLogin();
+ break;
+ }
+ return true;
+ }
+ };
+
+
+ //创建Menu
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.main_menu_setting, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ //Menu点击事件
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_search:
+ startActivity(new Intent(this, SearchActivity.class));
+ break;
+ default:
+ break;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ //退出登录
+ private void exitToLogin() {
+ IntentUtils.goLogin(this);
+ PreUtils.clearAll();
+ //刷新首页数据
+ RxEvent.getInstance().postEvent(Const.EVENT_ACTION.HOME, new Event(Event.Type.REFRESH_LIST));
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ setUserData();
+ }
+
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.btn_main:
+ index = 0;
+ break;
+ case R.id.btn_system:
+ index = 1;
+ break;
+ case R.id.btn_chapter:
+ index = 2;
+ break;
+ case R.id.btn_project:
+ index = 3;
+ break;
+ default:
+ }
+
+ showCurrentFragment(index);
+ }
+
+ /**
+ * 切换显示当前Fragment
+ *
+ * @param index
+ */
+ private void showCurrentFragment(int index) {
+ if (currentPosition != index) {
+ FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+ ft.hide(fragments[currentPosition]);
+ if (!fragments[index].isAdded()) {
+ ft.add(R.id.container, fragments[index]);
+ }
+ ft.show(fragments[index]).commit();
+ btns[currentPosition].setSelected(false);
+ btns[index].setSelected(true);
+ scaleView();
+ currentPosition = index;
+ setCurrentTitle();
+ }
+ }
+
+ /**
+ * view放大缩小
+ */
+ private void scaleView() {
+ btns[currentPosition].animate().scaleX(0.9f).scaleY(0.9f)
+ .setDuration(150).start();
+ btns[index].animate().scaleX(1.0f).scaleY(1.0f)
+ .setDuration(150).start();
+ }
+
+ private long mExitTime;
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+
+ if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
+
+ if (mDrawerLayout.isDrawerOpen(Gravity.START)) {
+ mDrawerLayout.closeDrawer(Gravity.START);
+ return true;
+ }
+
+ if (System.currentTimeMillis() - mExitTime < 2000) {
+ finish();
+ } else {
+ mExitTime = System.currentTimeMillis();
+ ToastUtils.showToast(AppContext.getContext(), "请再按一次退出程序");
+ }
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ protected void receiveEvent(Object object) {
+ Event event = (Event) object;
+ if (event.type == Event.Type.SCALE){
+ scroll((int) event.object);
+ }
+ }
+
+ public void scroll(int offsetY){
+ if (offsetY > 0 && btn_scroll_top.getVisibility() != View.INVISIBLE && !viewAnimatorHelper.isAnimating()){
+ viewAnimatorHelper.hideFloatActionButton();
+ }else if (offsetY < 0 && btn_scroll_top.getVisibility() != View.VISIBLE){
+ viewAnimatorHelper.showFloatActionButton();
+ }
+ }
+
+ @Override
+ protected String registerEvent() {
+ return Const.EVENT_ACTION.MAIN;
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/main/SearchActivity.java b/app/src/main/java/com/kdp/wanandroidclient/ui/main/SearchActivity.java
new file mode 100644
index 0000000..e3037c2
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/main/SearchActivity.java
@@ -0,0 +1,332 @@
+package com.kdp.wanandroidclient.ui.main;
+
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.widget.SearchView;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.kdp.wanandroidclient.R;
+import com.kdp.wanandroidclient.application.AppContext;
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.bean.Friend;
+import com.kdp.wanandroidclient.bean.Hotword;
+import com.kdp.wanandroidclient.common.Const;
+import com.kdp.wanandroidclient.event.Event;
+import com.kdp.wanandroidclient.inter.OnArticleListItemClickListener;
+import com.kdp.wanandroidclient.manager.UserInfoManager;
+import com.kdp.wanandroidclient.ui.adapter.ArticleListAdapter;
+import com.kdp.wanandroidclient.ui.adapter.BaseListAdapter;
+import com.kdp.wanandroidclient.ui.base.BaseAbListActivity;
+import com.kdp.wanandroidclient.ui.web.WebViewActivity;
+import com.kdp.wanandroidclient.utils.IntentUtils;
+import com.kdp.wanandroidclient.utils.ToastUtils;
+import com.zhy.view.flowlayout.FlowLayout;
+import com.zhy.view.flowlayout.TagAdapter;
+import com.zhy.view.flowlayout.TagFlowLayout;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * 搜索页面
+ * author: 曾文海
+ * date: 2023/5/31
+ */
+
+public class SearchActivity extends BaseAbListActivity implements SearchContract.ISearchView, OnArticleListItemClickListener {
+ private SearchView mSearchView;
+ private SearchView.SearchAutoComplete searchAutoComplete;
+ private View mHeaderView;
+ private TagFlowLayout mKeywordTagLayout, mFriendTagLayout;
+ private int position;
+ private int id;
+ private String keyword = "";
+ private List mHotwordDatas = new ArrayList<>();
+ private List mFriendDatas = new ArrayList<>();
+
+ @Override
+ protected boolean initToolbar() {
+ mToolbar.setTitle(R.string.search);
+ return true;
+ }
+
+ @Override
+ protected View initHeaderView() {
+ mHeaderView = LayoutInflater.from(this).inflate(R.layout.search_header, mRecyclerView, false);
+ mKeywordTagLayout = mHeaderView.findViewById(R.id.keywordTaglayout);
+ mFriendTagLayout = mHeaderView.findViewById(R.id.friendTaglayout);
+ return mHeaderView;
+ }
+
+ //设置搜索的数据
+ @Override
+ public void setData(List data) {
+ mRecyclerView.removeHeaderView();
+ setRefreshEnable(true);
+ setCanLoadMore(true);
+ if (state != Const.PAGE_STATE.STATE_LOAD_MORE)
+ mRecyclerView.scrollToPosition(0);
+ mListData.addAll(data);
+ }
+
+ @Override
+ public void showError() {
+ super.showError();
+ setRefreshEnable(true);
+ }
+
+
+ @Override
+ public String getKeyword() {
+ return keyword;
+ }
+
+
+ @Override
+ public int getArticleId() {
+ return id;
+ }
+
+ //热搜关键词
+ @Override
+ public void setHotwordData(final List mHotListDatas) {
+ mHotwordDatas.clear();
+ mHotwordDatas.addAll(mHotListDatas);
+ mKeywordTagLayout.setAdapter(new TagAdapter(mHotListDatas) {
+ @Override
+ public View getView(FlowLayout parent, int position, Hotword hotword) {
+ TextView tagView = (TextView) LayoutInflater.from(SearchActivity.this).inflate(R.layout.item_search_tag, mKeywordTagLayout, false);
+ tagView.setText(hotword.getName());
+ setTagTextColor(tagView);
+ return tagView;
+ }
+ });
+ mKeywordTagLayout.setOnTagClickListener(new TagFlowLayout.OnTagClickListener() {
+ @Override
+ public boolean onTagClick(View view, int position, FlowLayout parent) {
+ keyword = mHotListDatas.get(position).getName();
+ searchAutoComplete.setText(keyword);
+ searchAutoComplete.setSelection(keyword.length());
+ mSearchView.setQuery(keyword, true);
+ return false;
+ }
+ });
+ }
+
+ //历史网站
+ @Override
+ public void setFriendData(final List mFriendListDatas) {
+ mFriendDatas.clear();
+ mFriendDatas.addAll(mFriendListDatas);
+ mFriendTagLayout.setAdapter(new TagAdapter(mFriendDatas) {
+ @Override
+ public View getView(FlowLayout parent, int position, Friend friend) {
+ TextView tagView = (TextView) LayoutInflater.from(SearchActivity.this).inflate(R.layout.item_search_tag, mFriendTagLayout, false);
+ tagView.setText(friend.getName());
+ setTagTextColor(tagView);
+ return tagView;
+ }
+ });
+ mFriendTagLayout.setOnTagClickListener(
+
+ new TagFlowLayout.OnTagClickListener() {
+ @Override
+ public boolean onTagClick(View view, int position, FlowLayout parent) {
+ Friend mFriend = mFriendListDatas.get(position);
+ Article bean = new Article();
+ bean.setTitle(mFriend.getName());
+ bean.setLink(mFriend.getLink());
+ Intent intent = new Intent(SearchActivity.this, WebViewActivity.class);
+ Bundle bundle = new Bundle();
+ bundle.putSerializable(Const.BUNDLE_KEY.OBJ, bean);
+ intent.putExtras(bundle);
+ startActivity(intent);
+ return false;
+ }
+ });
+ }
+
+ //关键词颜色
+ private void setTagTextColor(TextView tagView) {
+ int red, green, blue;
+ Random mRandow = new Random();
+ red = mRandow.nextInt(255);
+ green = mRandow.nextInt(255);
+ blue = mRandow.nextInt(255);
+ int color = Color.rgb(red, green, blue);
+ tagView.setTextColor(color);
+ }
+
+ //SearchView相关设置
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.search_menu_setting, menu);
+ MenuItem menuItem = menu.findItem(R.id.menu_search);
+ //获取搜索框
+ mSearchView = (SearchView) menuItem.getActionView();
+ //设置搜索hint
+ mSearchView.setQueryHint(getString(R.string.search_keyword));
+ mSearchView.onActionViewExpanded();
+ //去除搜索框背景
+ deleteSearchPlate();
+ searchAutoComplete = mSearchView.findViewById(R.id.search_src_text);
+ searchAutoComplete.setHintTextColor(ContextCompat.getColor(this, R.color._60ffffff));
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ ImageView mCloseView = mSearchView.findViewById(R.id.search_close_btn);
+ mCloseView.setBackground(ContextCompat.getDrawable(this, R.drawable.ripple_close));
+ }
+
+ mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ keyword = query;
+ refreshData();
+ return false;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String newText) {
+ if (TextUtils.isEmpty(newText)) {
+ keyword = newText;
+ if (mHotwordDatas.size() == 0)
+ loadTagDatas();
+ }
+
+ return false;
+ }
+ });
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ //去除SearchView的输入框默认背景
+ private void deleteSearchPlate() {
+ try {
+ Class> cla = mSearchView.getClass();
+ Field mSearchPlateField = cla.getDeclaredField("mSearchPlate");
+ mSearchPlateField.setAccessible(true);
+ View searchPlate = (View) mSearchPlateField.get(mSearchView);
+ searchPlate.setBackground(null);
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ protected SearchPresenter createPresenter() {
+ return new SearchPresenter();
+ }
+
+ @Override
+ protected boolean isCanLoadMore() {
+ return true;
+ }
+
+ @Override
+ protected void loadDatas() {
+ if (mSearchView == null) {
+ loadTagDatas();
+ return;
+ }
+
+ loadArticleListDatas();
+ }
+
+ private void loadTagDatas() {
+ setRefreshEnable(false);
+ setCanLoadMore(false);
+ mListData.clear();
+ mRecyclerView.addHeaderView(mHeaderView);
+ mListAdapter.notifyAllDatas(mListData, mRecyclerView);
+ showContent();
+ mPresenter.getHotWord();
+ mPresenter.getFriend();
+ }
+
+ private void loadArticleListDatas() {
+ mHotwordDatas.clear();
+ mFriendDatas.clear();
+ mPresenter.search();
+ }
+
+ @Override
+ protected BaseListAdapter getListAdapter() {
+ return new ArticleListAdapter(this, Const.LIST_TYPE.SEARCH);
+ }
+
+ @Override
+ public void onItemClick(int position,Article bean) {
+ Intent intent = new Intent(this, WebViewActivity.class);
+ Bundle bundle = new Bundle();
+ bundle.putSerializable(Const.BUNDLE_KEY.OBJ, bean);
+ bundle.putString(Const.BUNDLE_KEY.TYPE, Const.EVENT_ACTION.SEARCH);
+ intent.putExtras(bundle);
+ startActivity(intent);
+ }
+
+ @Override
+ public void onDeleteCollectClick(int position, int id, int originId) {
+ }
+
+ @Override
+ public void collect(boolean isCollect, String result) {
+ notifyItemData(isCollect, result);
+ }
+
+ private void notifyItemData(boolean isCollect, String result) {
+ mListData.get(position).setCollect(isCollect);
+ mListAdapter.notifyItemDataChanged(position, mRecyclerView);
+ ToastUtils.showToast(AppContext.getContext(), result);
+ }
+
+ /**
+ * 收藏
+ * @param position
+ * @param id
+ */
+ @Override
+ public void onCollectClick(int position, int id) {
+ if (!UserInfoManager.isLogin())
+ IntentUtils.goLogin(this);
+ this.position = position;
+ this.id = id;
+ if (mListData.get(this.position).isCollect())
+ mPresenter.unCollectArticle();
+ else
+ mPresenter.collectArticle();
+ }
+
+ @Override
+ protected String registerEvent() {
+ return Const.EVENT_ACTION.SEARCH;
+ }
+
+ @Override
+ protected void receiveEvent(Object object) {
+ Event mEvent = (Event) object;
+ if (mEvent.type == Event.Type.REFRESH_ITEM) {
+ Article bean = (Article) mEvent.object;
+ for (int i = 0; i < mListData.size(); i++) {
+ if (bean.equals(mListData.get(i))) {
+ position = i;
+ notifyItemData(bean.isCollect(), getString(R.string.collect_success));
+ }
+ }
+ } else if (mEvent.type == Event.Type.REFRESH_LIST){
+ refreshData();
+ }
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/main/SearchContract.java b/app/src/main/java/com/kdp/wanandroidclient/ui/main/SearchContract.java
new file mode 100644
index 0000000..ccc435c
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/main/SearchContract.java
@@ -0,0 +1,40 @@
+package com.kdp.wanandroidclient.ui.main;
+
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.bean.Friend;
+import com.kdp.wanandroidclient.bean.Hotword;
+import com.kdp.wanandroidclient.ui.core.view.IPageLoadDataView;
+
+import java.util.List;
+
+/**
+ * 搜索协约类
+ * author: 曾文海
+ * date: 2023/5/31
+ */
+
+public class SearchContract {
+ interface ISearchPresenter {
+ void search();
+
+ void getHotWord();
+
+ void getFriend();
+
+ void collectArticle();
+
+ void unCollectArticle();
+ }
+
+ interface ISearchView extends IPageLoadDataView {
+ int getArticleId();//文章id
+
+ String getKeyword();
+
+ void setHotwordData(List mHotwordDatas);
+
+ void setFriendData(List mFriendListDatas);
+
+ void collect(boolean isCollect,String result);
+ }
+}
diff --git a/app/src/main/java/com/kdp/wanandroidclient/ui/main/SearchPresenter.java b/app/src/main/java/com/kdp/wanandroidclient/ui/main/SearchPresenter.java
new file mode 100644
index 0000000..3606a75
--- /dev/null
+++ b/app/src/main/java/com/kdp/wanandroidclient/ui/main/SearchPresenter.java
@@ -0,0 +1,142 @@
+package com.kdp.wanandroidclient.ui.main;
+
+import com.kdp.wanandroidclient.R;
+import com.kdp.wanandroidclient.application.AppContext;
+import com.kdp.wanandroidclient.bean.Article;
+import com.kdp.wanandroidclient.bean.Friend;
+import com.kdp.wanandroidclient.bean.Hotword;
+import com.kdp.wanandroidclient.net.callback.RxObserver;
+import com.kdp.wanandroidclient.net.callback.RxPageListObserver;
+import com.kdp.wanandroidclient.ui.core.model.impl.SearchModel;
+import com.kdp.wanandroidclient.ui.core.presenter.BasePresenter;
+
+import java.util.List;
+
+/**
+ * 搜索Presenter
+ * author: 曾文海
+ * date: 2023/5/31
+ */
+
+public class SearchPresenter extends BasePresenter implements SearchContract.ISearchPresenter {
+ private SearchModel searchModel;
+ private SearchContract.ISearchView searchView;
+
+ SearchPresenter() {
+ this.searchModel = new SearchModel();
+ }
+ /**
+ * 搜索文章
+ */
+ @Override
+ public void search() {
+ searchView = getView();
+ RxPageListObserver searchRxPageListObserver = new RxPageListObserver