baseList多接口-资讯页面(未完成)

This commit is contained in:
kehaoyuan
2018-03-20 15:22:20 +08:00
parent f9dbdd4aa8
commit b3ff6ea991
7 changed files with 147 additions and 336 deletions

View File

@ -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<T, VM extends ListViewModel /* 该泛型位
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Class<VM> 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<T, VM extends ListViewModel /* 该泛型位
provideListAdapter().provideListData(ts);
}
@Override
public Observable<List<T>> provideDataObservable(int offset) {
return null;
}
public void onLoadRefresh() {
mBaseHandler.postDelayed(() -> {
provideListAdapter().loadChange(LoadStatus.REFRESH);

View File

@ -41,7 +41,7 @@ public class ListRepository<T> {
Observable<List<T>> 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;
}

View File

@ -19,24 +19,22 @@ public class ListViewModel<T> extends AndroidViewModel implements OnDataObservab
private ListRepository mRepository;
private LiveData<List<T>> mLiveListData;
protected LiveData<List<T>> 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<List<T>> getObsListData() {
return mLiveListData;
return mListLiveData;
}
public LiveData<LoadStatus> getLoadStatusLiveData() {

View File

@ -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<NewsEntity> {
MediatorLiveData<List<NewsEntity>> mNewsListLiveData = new MediatorLiveData<>();
NewsViewsRepository<ViewsEntity> mNewsViewsRepository = new NewsViewsRepository<>();
public InFoViewModel(@NonNull Application application) {
super(application);
mNewsListLiveData.addSource(mListLiveData, (Observer<List<NewsEntity>>) 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<List<ViewsEntity>> listLiveData = mNewsViewsRepository.asLiveData();
mNewsListLiveData.addSource(listLiveData, new Observer<List<ViewsEntity>>() {
@Override
public void onChanged(@Nullable List<ViewsEntity> viewsEntities) {
// todo 此处有问题
List<NewsEntity> 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<List<NewsEntity>> getObsListData() {
return mNewsListLiveData;
}
@Override
public Observable<List<NewsEntity>> provideDataObservable(int offset) {
return RetrofitManager.getInstance(getApplication()).getApi().getZiXun(offset);
}
}

View File

@ -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<ViewHolder> {
class InfoAdapter extends ListAdapter<NewsEntity> {
private OnRequestCallBackListener listener;
private OnListClickListener mListListener;
private List<NewsEntity> 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<ViewHolder> {
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<ViewHolder> {
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<ViewHolder> {
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<ViewHolder> {
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<ViewHolder> {
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<ViewHolder> {
});
}
// 加载数据
public void addList(final int offset) {
if (isLoading) {
return;
}
isLoading = true;
RetrofitManager.getInstance(mContext).getApi()
.getZiXun(offset)
.map(new Func1<List<NewsEntity>, List<NewsEntity>>() {
@Override
public List<NewsEntity> call(List<NewsEntity> list) {
// 去掉重复数据
Config.filterPluginArticle(list);
return NewsUtils.removeDuplicateData(newsList, list);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<List<NewsEntity>>() {
@Override
public void onResponse(List<NewsEntity> 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<NewsEntity> list, final int start) {
if (list == null || list.isEmpty()) {
return;
}
ObservableUtil.computation(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> 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<String>() {
@Override
public void call(String ids) {
RetrofitManager.getInstance(mContext).getData()
.getNewsViews(ids)
.map(new Func1<List<ViewsEntity>, String>() {
@Override
public String call(List<ViewsEntity> 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<String>() {
@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<ViewHolder> {
@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;
}
}

View File

@ -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<List<NewsEntity>, 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<NewsEntity> newsList = (List<NewsEntity>) 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 + "])"));
}
}

View File

@ -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<T> {
private final MediatorLiveData<List<T>> result = new MediatorLiveData<>();
// 获取新闻阅读量
public void getNewsViews(Observable<List<T>> observable) {
observable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Response<List<T>>() {
@Override
public void onResponse(List<T> response) {
result.postValue(response);
}
});
}
public LiveData<List<T>> asLiveData() {
return result;
}
}