package com.linroid.sky31radio.ui.fragment; import android.os.Bundle; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.google.gson.reflect.TypeToken; import com.linroid.sky31radio.R; import com.linroid.sky31radio.data.ApiService; import com.linroid.sky31radio.data.DiskCacheManager; import com.linroid.sky31radio.model.Album; import com.linroid.sky31radio.model.Anchor; import com.linroid.sky31radio.model.Pagination; import com.linroid.sky31radio.model.Program; import com.linroid.sky31radio.ui.adapter.ProgramAdapter; import com.linroid.sky31radio.ui.base.InjectableFragment; import com.linroid.sky31radio.view.ContentLoaderView; import com.linroid.sky31radio.view.DividerItemDecoration; import com.squareup.picasso.Picasso; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import butterknife.ButterKnife; import butterknife.InjectView; import rx.Observable; import rx.Observer; import rx.Subscriber; import rx.android.app.AppObservable; import rx.functions.Func1; import timber.log.Timber; public class ProgramListFragment extends InjectableFragment implements ContentLoaderView.OnRefreshListener, ContentLoaderView.OnMoreListener { public static final String KEY_PROGRAM = "program"; public static final String EXTRA_ALBUM = "album"; public static final String EXTRA_ANCHOR = "anchor"; @InjectView(R.id.recycler) RecyclerView recyclerView; @InjectView(R.id.content_loader) ContentLoaderView loaderView; @Inject Picasso picasso; @Inject DiskCacheManager cacheManager; @Inject ApiService apiService; ProgramAdapter adapter; protected Map<String, String> conditions; boolean hasLoaded = false; public static ProgramListFragment newInstance() { ProgramListFragment fragment = new ProgramListFragment(); Bundle args = new Bundle(); fragment.setArguments(args); return fragment; } public static ProgramListFragment newInstance(Anchor anchor) { ProgramListFragment fragment = new ProgramListFragment(); Bundle args = new Bundle(); args.putParcelable(EXTRA_ANCHOR, anchor); fragment.setArguments(args); return fragment; } public static ProgramListFragment newInstance(Album album) { ProgramListFragment fragment = new ProgramListFragment(); Bundle args = new Bundle(); args.putParcelable(EXTRA_ALBUM, album); fragment.setArguments(args); return fragment; } public ProgramListFragment() { // Required empty public constructor } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); conditions = new HashMap<>(); Bundle data = getArguments(); if (data != null) { if (data.containsKey(EXTRA_ALBUM)) { Album album = data.getParcelable(EXTRA_ALBUM); conditions.put("album_id", String.valueOf(album.getId())); } if (data.containsKey(EXTRA_ANCHOR)) { Anchor anchor = data.getParcelable(EXTRA_ANCHOR); conditions.put("user_id", String.valueOf(anchor.getId())); } } adapter = new ProgramAdapter(picasso); if (savedInstanceState != null) { List<Program> programList = savedInstanceState.getParcelableArrayList(KEY_PROGRAM); adapter.setListData(programList); }else{ loadData(1); } } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putParcelableArrayList(KEY_PROGRAM, (ArrayList<Program>) adapter.getProgramList()); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Timber.i("onCreateView"); ViewGroup view = (ViewGroup) inflater.inflate(R.layout.fragment_program_list, container, false); ButterKnife.inject(this, view); recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); recyclerView.setItemAnimator(new DefaultItemAnimator()); recyclerView.setHasFixedSize(true); recyclerView.addItemDecoration(new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL_LIST)); loaderView.setAdapter(adapter); loaderView.setOnRefreshListener(this); loaderView.setMoreListener(this); return view; } @Override public void onDestroyView() { super.onDestroyView(); } public void loadData(int page) { if(!hasLoaded && conditions.size()==0){ AppObservable.bindFragment(this, Observable.create(new Observable.OnSubscribe<Pagination<Program>>() { @Override public void call(Subscriber<? super Pagination<Program>> subscriber) { if (cacheManager.exits(DiskCacheManager.KEY_PROGRAM)) { Type type = new TypeToken<Pagination<Program>>() { }.getType(); Pagination<Program> cachedData = cacheManager.get(DiskCacheManager.KEY_PROGRAM, type); Timber.d("load data from cached file successful!"); if (cachedData != null) { subscriber.onNext(cachedData); } } } }) ).subscribe(observer); } AppObservable.bindFragment(this, apiService.listPrograms(page, conditions)) .map(new Func1<Pagination<Program>, Pagination<Program>>() { @Override public Pagination<Program> call(Pagination<Program> pagination) { if(pagination.getCurrentPage() == 1 && conditions.size()==0){ cacheManager.put(DiskCacheManager.KEY_PROGRAM, pagination); } return pagination; } }).subscribe(observer); } Observer<Pagination<Program>> observer = new Observer<Pagination<Program>>() { @Override public void onCompleted() { Timber.i("listPrograms onCompleted"); } @Override public void onError(Throwable throwable) { Timber.e(throwable, "listPrograms onError"); loaderView.notifyLoadFailed(throwable); } @Override public void onNext(Pagination<Program> pagination) { hasLoaded = true; Timber.i("listPrograms onNext, currentPage:%d, total:%d", pagination.getCurrentPage(), pagination.getTotal()); if (pagination.getCurrentPage() > 1) { int previousIndex = adapter.getProgramList().size(); adapter.addMoreData(pagination.getData()); adapter.notifyItemRangeInserted(previousIndex, pagination.getData().size()); } else { adapter.setListData(pagination.getData()); adapter.notifyDataSetChanged(); } loaderView.setPage(pagination.getCurrentPage(), pagination.getLastPage()); } }; @Override public void onRefresh(boolean fromSwipe) { loadData(1); } @Override public void onMore(int page) { loadData(page); } }