diff --git a/app/src/main/java/com/gh/gamecenter/baselist/ListFragment.java b/app/src/main/java/com/gh/gamecenter/baselist/ListFragment.java index d88add6313..1d3340fbd8 100644 --- a/app/src/main/java/com/gh/gamecenter/baselist/ListFragment.java +++ b/app/src/main/java/com/gh/gamecenter/baselist/ListFragment.java @@ -22,6 +22,7 @@ import java.lang.reflect.Type; import java.util.List; import butterknife.BindView; +import rx.Observable; /** * Created by khy on 2/12/17. @@ -69,13 +70,8 @@ public abstract class ListFragment viewModelClass = getViewModelClass(); - if (ListViewModel.class.getName().equals(viewModelClass.getName())) { - final ListViewModel.Factory factory = new ListViewModel.Factory(HaloApp.getInstance().getApplication(), this); - mListViewModel = ViewModelProviders.of(this, factory).get(viewModelClass); - } else { - mListViewModel = ViewModelProviders.of(this).get(viewModelClass); - } - + final VM.Factory factory = new VM.Factory(HaloApp.getInstance().getApplication(), this); + mListViewModel = ViewModelProviders.of(this, factory).get(viewModelClass); mListViewModel.getObsListData().observe(this, this); mListViewModel.getLoadStatusLiveData().observe(this, o -> { if (o instanceof LoadStatus) { @@ -147,6 +143,11 @@ public abstract class ListFragment> provideDataObservable(int offset) { + return null; + } + public void onLoadRefresh() { mBaseHandler.postDelayed(() -> { provideListAdapter().loadChange(LoadStatus.REFRESH); diff --git a/app/src/main/java/com/gh/gamecenter/baselist/ListRepository.java b/app/src/main/java/com/gh/gamecenter/baselist/ListRepository.java index 6fbba441d8..d497e0d864 100644 --- a/app/src/main/java/com/gh/gamecenter/baselist/ListRepository.java +++ b/app/src/main/java/com/gh/gamecenter/baselist/ListRepository.java @@ -41,7 +41,7 @@ public class ListRepository { Observable> listObservable = mDataObservable.provideDataObservable(loadParams.getLoadOffset()); LoadStatus curStatus = mLoadStatusLiveData.getValue(); - if (curStatus != null && curStatus != LoadStatus.INIT_LOADED && curStatus != LoadStatus.LIST_LOADED) { + if (listObservable == null || curStatus != null && curStatus != LoadStatus.INIT_LOADED && curStatus != LoadStatus.LIST_LOADED) { return; } diff --git a/app/src/main/java/com/gh/gamecenter/baselist/ListViewModel.java b/app/src/main/java/com/gh/gamecenter/baselist/ListViewModel.java index 96014757b1..415c33d81e 100644 --- a/app/src/main/java/com/gh/gamecenter/baselist/ListViewModel.java +++ b/app/src/main/java/com/gh/gamecenter/baselist/ListViewModel.java @@ -19,24 +19,22 @@ public class ListViewModel extends AndroidViewModel implements OnDataObservab private ListRepository mRepository; - private LiveData> mLiveListData; + protected LiveData> mListLiveData; public ListViewModel(Application application, ListRepository repository) { super(application); mRepository = repository; - mLiveListData = mRepository.getResultLiveData(); - + mListLiveData = mRepository.getResultLiveData(); } public ListViewModel(@NonNull Application application) { super(application); mRepository = new ListRepository(this); - } public LiveData> getObsListData() { - return mLiveListData; + return mListLiveData; } public LiveData getLoadStatusLiveData() { diff --git a/app/src/main/java/com/gh/gamecenter/info/InFoViewModel.java b/app/src/main/java/com/gh/gamecenter/info/InFoViewModel.java new file mode 100644 index 0000000000..fd3ba66112 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/info/InFoViewModel.java @@ -0,0 +1,73 @@ +package com.gh.gamecenter.info; + +import android.app.Application; +import android.arch.lifecycle.LiveData; +import android.arch.lifecycle.MediatorLiveData; +import android.arch.lifecycle.Observer; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import com.gh.gamecenter.baselist.ListViewModel; +import com.gh.gamecenter.entity.NewsEntity; +import com.gh.gamecenter.entity.ViewsEntity; +import com.gh.gamecenter.retrofit.RetrofitManager; + +import java.util.List; + +import rx.Observable; + +/** + * Created by khy on 19/03/18. + */ + +public class InFoViewModel extends ListViewModel { + + MediatorLiveData> mNewsListLiveData = new MediatorLiveData<>(); + + NewsViewsRepository mNewsViewsRepository = new NewsViewsRepository<>(); + + public InFoViewModel(@NonNull Application application) { + super(application); + mNewsListLiveData.addSource(mListLiveData, (Observer>) list -> { + if (list == null) return; + StringBuilder builder = new StringBuilder(); + for (int i = 0, size = list.size(); i < size; i++) { + builder.append(list.get(i).getId()); + builder.append("-"); + } + builder.deleteCharAt(builder.length() - 1); + String ids = builder.toString(); + + mNewsViewsRepository.getNewsViews(RetrofitManager.getInstance(getApplication()).getData().getNewsViews(ids)); + }); + + LiveData> listLiveData = mNewsViewsRepository.asLiveData(); + + mNewsListLiveData.addSource(listLiveData, new Observer>() { + @Override + public void onChanged(@Nullable List viewsEntities) { + // todo 此处有问题 + List value = mNewsListLiveData.getValue(); + for (ViewsEntity viewsEntity : viewsEntities) { + for (NewsEntity newsEntity : value) { + if (viewsEntity.getId().equals(newsEntity.getId())) { + newsEntity.setViews(viewsEntity.getViews()); + break; + } + } + } + mNewsListLiveData.postValue(value); + } + }); + } + + @Override + public LiveData> getObsListData() { + return mNewsListLiveData; + } + + @Override + public Observable> provideDataObservable(int offset) { + return RetrofitManager.getInstance(getApplication()).getApi().getZiXun(offset); + } +} diff --git a/app/src/main/java/com/gh/gamecenter/info/InfoAdapter.java b/app/src/main/java/com/gh/gamecenter/info/InfoAdapter.java index ffde9501e2..3591dc7253 100644 --- a/app/src/main/java/com/gh/gamecenter/info/InfoAdapter.java +++ b/app/src/main/java/com/gh/gamecenter/info/InfoAdapter.java @@ -2,15 +2,12 @@ package com.gh.gamecenter.info; import android.content.Context; import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.RecyclerView.ViewHolder; import android.util.DisplayMetrics; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import com.gh.base.OnListClickListener; -import com.gh.base.OnRequestCallBackListener; -import com.gh.common.constant.Config; import com.gh.common.constant.ItemViewType; import com.gh.common.util.DisplayUtils; import com.gh.common.util.ImageUtils; @@ -20,29 +17,18 @@ import com.gh.gamecenter.adapter.viewholder.FooterViewHolder; import com.gh.gamecenter.adapter.viewholder.NewsImage1ViewHolder; import com.gh.gamecenter.adapter.viewholder.NewsImage2ViewHolder; import com.gh.gamecenter.adapter.viewholder.NewsImage3ViewHolder; +import com.gh.gamecenter.baselist.ListAdapter; import com.gh.gamecenter.entity.NewsEntity; -import com.gh.gamecenter.entity.ViewsEntity; import com.gh.gamecenter.manager.VisitManager; import com.gh.gamecenter.retrofit.JSONObjectResponse; -import com.gh.gamecenter.retrofit.ObservableUtil; -import com.gh.gamecenter.retrofit.Response; import com.gh.gamecenter.retrofit.RetrofitManager; -import com.lightgame.adapter.BaseRecyclerAdapter; -import com.lightgame.utils.Utils; import org.json.JSONException; import org.json.JSONObject; -import java.util.ArrayList; -import java.util.List; import java.util.Locale; -import retrofit2.HttpException; -import rx.Observable; -import rx.Subscriber; import rx.android.schedulers.AndroidSchedulers; -import rx.functions.Action1; -import rx.functions.Func1; import rx.schedulers.Schedulers; @@ -50,32 +36,13 @@ import rx.schedulers.Schedulers; * Created by khy on 2016/6/30. * 资讯-资讯-数据适配器 */ -class InfoAdapter extends BaseRecyclerAdapter { +class InfoAdapter extends ListAdapter { - private OnRequestCallBackListener listener; private OnListClickListener mListListener; - private List newsList; - - private int itemCount; - - private boolean isLoading; - private boolean isOver; - private boolean isNetworkError; - - InfoAdapter(Context context, OnRequestCallBackListener listener, OnListClickListener listListener) { + InfoAdapter(Context context, OnListClickListener listListener) { super(context); this.mListListener = listListener; - this.listener = listener; - - newsList = new ArrayList<>(); - - itemCount = 0; - - isLoading = false; - isOver = false; - isNetworkError = false; - } @Override @@ -84,13 +51,13 @@ class InfoAdapter extends BaseRecyclerAdapter { switch (viewType) { case ItemViewType.NEWS_IMAGE1: view = mLayoutInflater.inflate(R.layout.news_image1_item, parent, false); - return new NewsImage1ViewHolder(view, newsList, mListListener); + return new NewsImage1ViewHolder(view, mEntityList, mListListener); case ItemViewType.NEWS_IMAGE2: view = mLayoutInflater.inflate(R.layout.news_image2_item, parent, false); - return new NewsImage2ViewHolder(view, newsList, mListListener); + return new NewsImage2ViewHolder(view, mEntityList, mListListener); case ItemViewType.NEWS_IMAGE3: view = mLayoutInflater.inflate(R.layout.news_image3_item, parent, false); - return new NewsImage3ViewHolder(view, newsList, mListListener); + return new NewsImage3ViewHolder(view, mEntityList, mListListener); case ItemViewType.LOADING: return new FooterViewHolder(mLayoutInflater.inflate(R.layout.refresh_footerview, parent, false)); default: @@ -111,14 +78,16 @@ class InfoAdapter extends BaseRecyclerAdapter { initNewsImage3ViewHolder((NewsImage3ViewHolder) holder, position); break; case ItemViewType.LOADING: - initFooterViewHolder((FooterViewHolder) holder); + FooterViewHolder footerViewHolder = (FooterViewHolder) holder; + footerViewHolder.initItemPadding(); + footerViewHolder.initFooterViewHolder(mIsNetworkError, mIsOver, R.string.ask_loadover_hint); break; } } private void initNewsImage1ViewHolder(final NewsImage1ViewHolder viewHolder, int position) { - final NewsEntity newsEntity = newsList.get(position); + final NewsEntity newsEntity = mEntityList.get(position); ImageUtils.Companion.display(viewHolder.thumb, newsEntity.getThumbnail().getUrl().get(0)); viewHolder.title.setText(newsEntity.getTitle()); int views = newsEntity.getViews(); @@ -133,7 +102,7 @@ class InfoAdapter extends BaseRecyclerAdapter { private void initNewsImage2ViewHolder(final NewsImage2ViewHolder viewHolder, int position) { - final NewsEntity newsEntity = newsList.get(position); + final NewsEntity newsEntity = mEntityList.get(position); DisplayMetrics outMetrics = new DisplayMetrics(); int width = (outMetrics.widthPixels - DisplayUtils.dip2px(mContext, 56)) / 3; @@ -167,7 +136,7 @@ class InfoAdapter extends BaseRecyclerAdapter { private void initNewsImage3ViewHolder(final NewsImage3ViewHolder viewHolder, int position) { - final NewsEntity newsEntity = newsList.get(position); + final NewsEntity newsEntity = mEntityList.get(position); viewHolder.title.setText(newsEntity.getTitle()); ImageUtils.Companion.getInstance().display(viewHolder.thumb, newsEntity.getThumbnail().getUrl().get(0), @@ -182,30 +151,6 @@ class InfoAdapter extends BaseRecyclerAdapter { NewsUtils.setNewsType(viewHolder.type, newsEntity.getType(), newsEntity.getPriority(), position); } - private void initFooterViewHolder(FooterViewHolder viewHolder) { - viewHolder.initItemPadding(); - if (isNetworkError) { - viewHolder.loading.setVisibility(View.GONE); - viewHolder.hint.setText(R.string.loading_failed_retry); - viewHolder.itemView.setClickable(true); - viewHolder.itemView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - isNetworkError = false; - notifyItemChanged(getItemCount() - 1); - addList(newsList.size()); - } - }); - } else if (isOver) { - viewHolder.loading.setVisibility(View.GONE); - viewHolder.hint.setText(R.string.loading_complete); - viewHolder.itemView.setClickable(false); - } else { - viewHolder.loading.setVisibility(View.VISIBLE); - viewHolder.hint.setText(R.string.loading); - viewHolder.itemView.setClickable(false); - } - } // 统计新闻阅读量 public void statNewsViews(final NewsEntity newsEntity, final int position) { @@ -233,119 +178,13 @@ class InfoAdapter extends BaseRecyclerAdapter { }); } - // 加载数据 - public void addList(final int offset) { - if (isLoading) { - return; - } - isLoading = true; - RetrofitManager.getInstance(mContext).getApi() - .getZiXun(offset) - .map(new Func1, List>() { - @Override - public List call(List list) { - // 去掉重复数据 - Config.filterPluginArticle(list); - return NewsUtils.removeDuplicateData(newsList, list); - } - }) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Response>() { - @Override - public void onResponse(List response) { - isLoading = false; - - if (response.size() != 0) { - newsList.addAll(response); - itemCount += response.size(); - notifyItemRangeInserted(newsList.size() - response.size(), response.size()); - } else { - isOver = true; - notifyItemChanged(getItemCount() - 1); - } - - if (offset == 0 && listener != null) { - listener.loadDone(); - } - - // 获取新闻阅读量 - getNewsViews(response, offset); - } - - @Override - public void onFailure(HttpException e) { - isLoading = false; - // 网络错误 - if (offset == 0) { - if (listener != null) { - listener.loadError(); - } - } else { - Utils.toast(mContext, R.string.loading_failed_hint); - isNetworkError = true; - notifyItemChanged(getItemCount() - 1); - } - } - }); - } - - // 获取新闻阅读量 - private void getNewsViews(final List list, final int start) { - if (list == null || list.isEmpty()) { - return; - } - ObservableUtil.computation(new Observable.OnSubscribe() { - @Override - public void call(Subscriber subscriber) { - StringBuilder builder = new StringBuilder(); - for (int i = 0, size = list.size(); i < size; i++) { - builder.append(list.get(i).getId()); - builder.append("-"); - } - builder.deleteCharAt(builder.length() - 1); - String ids = builder.toString(); - VisitManager.getInstance().addUrl(ids); - subscriber.onNext(ids); - subscriber.onCompleted(); - } - }, new Action1() { - @Override - public void call(String ids) { - RetrofitManager.getInstance(mContext).getData() - .getNewsViews(ids) - .map(new Func1, String>() { - @Override - public String call(List list) { - for (ViewsEntity viewsEntity : list) { - for (NewsEntity newsEntity : newsList) { - if (viewsEntity.getId().equals(newsEntity.getId())) { - newsEntity.setViews(viewsEntity.getViews()); - break; - } - } - } - return null; - } - }) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Response() { - @Override - public void onResponse(String response) { - notifyItemRangeChanged(start, list.size()); - } - }); - } - }); - } @Override public int getItemViewType(int position) { - if (position == newsList.size()) { + if (position == getItemCount() - 1) { return ItemViewType.LOADING; } - NewsEntity newsEntity = newsList.get(position); + NewsEntity newsEntity = mEntityList.get(position); if ("4x3".equals(newsEntity.getThumbnail().getType()) && newsEntity.getThumbnail().getUrl().size() == 3) { return ItemViewType.NEWS_IMAGE2; } @@ -357,29 +196,6 @@ class InfoAdapter extends BaseRecyclerAdapter { @Override public int getItemCount() { - if (itemCount == 0) { - return 0; - } - return itemCount + 1; - } - - public boolean isOver() { - return isOver; - } - - public boolean isLoading() { - return isLoading; - } - - public boolean isNetworkError() { - return isNetworkError; - } - - public void setNetworkError(boolean networkError) { - isNetworkError = networkError; - } - - public int getNewsListSize() { - return newsList.size(); + return mEntityList == null || mEntityList.isEmpty() ? 0 : mEntityList.size() + FOOTER_ITEM_COUNT; } } diff --git a/app/src/main/java/com/gh/gamecenter/info/InfoFragment.java b/app/src/main/java/com/gh/gamecenter/info/InfoFragment.java index d493f7a35f..1547c4e5e2 100644 --- a/app/src/main/java/com/gh/gamecenter/info/InfoFragment.java +++ b/app/src/main/java/com/gh/gamecenter/info/InfoFragment.java @@ -1,148 +1,32 @@ package com.gh.gamecenter.info; -import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v4.widget.SwipeRefreshLayout; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.view.View; -import android.widget.LinearLayout; -import com.gc.materialdesign.views.ProgressBarCircularIndeterminate; -import com.gh.base.fragment.BaseFragment; import com.gh.common.util.DataCollectionUtils; -import com.gh.gamecenter.DataUtils; import com.gh.common.util.StringUtils; -import com.gh.common.view.VerticalItemDecoration; +import com.gh.gamecenter.DataUtils; import com.gh.gamecenter.NewsDetailActivity; -import com.gh.gamecenter.R; +import com.gh.gamecenter.baselist.ListAdapter; +import com.gh.gamecenter.baselist.ListFragment; import com.gh.gamecenter.entity.NewsEntity; -import com.gh.gamecenter.eventbus.EBNetworkState; -import com.gh.gamecenter.eventbus.EBUISwitch; - -import org.greenrobot.eventbus.Subscribe; -import org.greenrobot.eventbus.ThreadMode; import java.util.HashMap; import java.util.List; import java.util.Map; -import butterknife.BindView; -import butterknife.OnClick; - /** * Created by LGT on 2016/6/29. * 资讯-资讯界面 */ -public class InfoFragment extends BaseFragment implements SwipeRefreshLayout.OnRefreshListener { +public class InfoFragment extends ListFragment, InFoViewModel> { - @BindView(R.id.info_srl_refresh) - SwipeRefreshLayout refreshLayout; - @BindView(R.id.info_rv_list) - RecyclerView recyclerView; - @BindView(R.id.info_pb_loading) - ProgressBarCircularIndeterminate loadingLayout; - @BindView(R.id.reuse_no_connection) - LinearLayout noConnectionLayout; - - private LinearLayoutManager layoutManager; - private InfoAdapter adapter; - - Runnable runnable = new Runnable() { - @Override - public void run() { - adapter = new InfoAdapter(getContext(), InfoFragment.this, InfoFragment.this); - recyclerView.setAdapter(adapter); - adapter.addList(0); - } - }; + private InfoAdapter mAdapter; @Override - protected int getLayoutId() { - return R.layout.fragment_info_info; + protected ListAdapter provideListAdapter() { + return mAdapter == null ? mAdapter = new InfoAdapter(getContext(), this) : mAdapter; } - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - refreshLayout.setColorSchemeResources(R.color.theme); - refreshLayout.setOnRefreshListener(this); - - recyclerView.setHasFixedSize(true); - layoutManager = new LinearLayoutManager(getActivity()); - recyclerView.setLayoutManager(layoutManager); - recyclerView.addItemDecoration(new VerticalItemDecoration(getContext(), 8, true)); - adapter = new InfoAdapter(getContext(), this, this); - recyclerView.setAdapter(adapter); - recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - if (newState == RecyclerView.SCROLL_STATE_IDLE - && layoutManager.findLastVisibleItemPosition() + 1 == adapter.getItemCount()) { - if (!adapter.isOver() && !adapter.isLoading() && !adapter.isNetworkError()) { - adapter.addList(adapter.getNewsListSize()); - } - } - } - }); - } - - @Override - public void loadDone() { // 数据加载成功回调 - refreshLayout.setRefreshing(false); - loadingLayout.setVisibility(View.GONE); - } - - @Override - public void loadError() { // 数据加载失败回调 - refreshLayout.setRefreshing(false); - loadingLayout.setVisibility(View.GONE); - recyclerView.setVisibility(View.GONE); - noConnectionLayout.setVisibility(View.VISIBLE); - } - - // 连接上网络事件 - @Subscribe(threadMode = ThreadMode.MAIN) - public void onEventMainThread(EBNetworkState busNetworkState) { - if (busNetworkState.isNetworkConnected()) { - if (noConnectionLayout.getVisibility() == View.VISIBLE) { - reconnection(); - } else if (adapter.isNetworkError()) { - adapter.setNetworkError(false); - adapter.notifyItemChanged(adapter.getItemCount() - 1); - adapter.addList(adapter.getNewsListSize()); - } - } - } - - @OnClick(R.id.reuse_no_connection) - public void reconnection() { // 重新连接 - refreshLayout.setRefreshing(true); - recyclerView.setVisibility(View.VISIBLE); - loadingLayout.setVisibility(View.VISIBLE); - noConnectionLayout.setVisibility(View.GONE); - postDelayedRunnable(runnable, 1000); - } - - // 资讯Fragment界面切换事件 - @Subscribe(threadMode = ThreadMode.MAIN) - public void onEventMainThread(EBUISwitch busNine) { - if (InfoToolWrapperFragment.EB_NEWSFRAGMENT_TAG.equals(busNine.getFrom())) { - if (busNine.getPosition() == 0) { - if (loadingLayout.getVisibility() == View.VISIBLE) { - adapter.addList(0); - } - } - } - } - - @Override - public void onRefresh() { // 刷新 - postDelayedRunnable(runnable, 1000); - } - - @Override public void onListClick(View view, int position, Object data) { List newsList = (List) data; @@ -155,7 +39,7 @@ public class InfoFragment extends BaseFragment implements SwipeRefreshLayout.OnR DataCollectionUtils.uploadClick(getContext(), "列表", "资讯-资讯", newsEntity.getTitle()); //统计阅读量 - adapter.statNewsViews(newsEntity, position); + mAdapter.statNewsViews(newsEntity, position); NewsDetailActivity.startNewsDetailActivity(getContext(), newsEntity, StringUtils.buildString("(资讯:资讯[" + position + "])")); } } diff --git a/app/src/main/java/com/gh/gamecenter/info/NewsViewsRepository.java b/app/src/main/java/com/gh/gamecenter/info/NewsViewsRepository.java new file mode 100644 index 0000000000..37123b59d7 --- /dev/null +++ b/app/src/main/java/com/gh/gamecenter/info/NewsViewsRepository.java @@ -0,0 +1,39 @@ +package com.gh.gamecenter.info; + +import android.arch.lifecycle.LiveData; +import android.arch.lifecycle.MediatorLiveData; + +import com.gh.gamecenter.retrofit.Response; + +import java.util.List; + +import rx.Observable; +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; + +/** + * Created by khy on 19/03/18. + */ + +public class NewsViewsRepository { + + private final MediatorLiveData> result = new MediatorLiveData<>(); + + // 获取新闻阅读量 + public void getNewsViews(Observable> observable) { + observable + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Response>() { + @Override + public void onResponse(List response) { + result.postValue(response); + } + }); + + } + + public LiveData> asLiveData() { + return result; + } +}