package com.example.fragment; import android.content.Context; 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.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import com.example.R; import com.example.adapter.RecyclerAdapter; import com.example.entity.ProductEntity; import com.example.task.LoadDataTask; import com.example.widget.LinearDividerItemDecoration; import org.alfonz.utility.Logcat; import org.alfonz.utility.NetworkUtility; import org.alfonz.view.StatefulLayout; import java.util.ArrayList; import java.util.List; public class RecyclerFragment extends TaskFragment implements LoadDataTask.OnLoadDataListener, RecyclerAdapter.ProductViewHolder.OnItemClickListener { private static final int LAZY_LOADING_TAKE = 16; private static final int LAZY_LOADING_OFFSET = 4; private boolean mLazyLoading = false; private View mRootView; private StatefulLayout mStatefulLayout; private RecyclerAdapter mAdapter; private LoadDataTask mLoadDataTask; private List<String> mHeaderList = new ArrayList<>(); private List<ProductEntity> mProductList = new ArrayList<>(); private List<Object> mFooterList = new ArrayList<>(); @Override public void onAttach(Context context) { super.onAttach(context); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); setRetainInstance(true); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mRootView = inflater.inflate(R.layout.fragment_recycler, container, false); setupRecyclerView(); return mRootView; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // setup stateful layout setupStatefulLayout(savedInstanceState); // load data if(mProductList == null || mProductList.isEmpty()) loadData(); // lazy loading progress if(mLazyLoading) showLazyLoadingProgress(true); } @Override public void onStart() { super.onStart(); } @Override public void onResume() { super.onResume(); } @Override public void onPause() { super.onPause(); // stop adapter if(mAdapter != null) mAdapter.stop(); } @Override public void onStop() { super.onStop(); } @Override public void onDestroyView() { super.onDestroyView(); mRootView = null; } @Override public void onDestroy() { super.onDestroy(); // cancel async tasks if(mLoadDataTask != null) mLoadDataTask.cancel(true); } @Override public void onDetach() { super.onDetach(); } @Override public void onSaveInstanceState(Bundle outState) { // save current instance state super.onSaveInstanceState(outState); setUserVisibleHint(true); // stateful layout state if(mStatefulLayout != null) mStatefulLayout.saveInstanceState(outState); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { // action bar menu super.onCreateOptionsMenu(menu, inflater); // TODO } @Override public boolean onOptionsItemSelected(MenuItem item) { // action bar menu behavior return super.onOptionsItemSelected(item); // TODO } @Override public void onItemClick(View view, int position, long id, int viewType) { // position int productPosition = mAdapter.getProductPosition(position); // TODO } @Override public void onItemLongClick(View view, int position, long id, int viewType) { // position int productPosition = mAdapter.getProductPosition(position); // TODO } @Override public void onLoadData() { runTaskCallback(new Runnable() { public void run() { if(mRootView == null) return; // view was destroyed // get data final int size = mProductList.size(); for(int i = 0; i < LAZY_LOADING_TAKE; i++) { ProductEntity p = new ProductEntity(); p.setName("Product " + (size + i)); mProductList.add(p); } if(mHeaderList.size() == 0) { mHeaderList.add("One"); mHeaderList.add("Two"); mHeaderList.add("Three"); } // show content if(mProductList != null && mProductList.size() > 0) mStatefulLayout.showContent(); else mStatefulLayout.showEmpty(); showLazyLoadingProgress(false); } }); } private void loadData() { if(NetworkUtility.isOnline(getActivity())) { // show progress mStatefulLayout.showProgress(); // run async task mLoadDataTask = new LoadDataTask(this); executeTask(mLoadDataTask); } else { mStatefulLayout.showOffline(); } } private void lazyLoadData() { if(NetworkUtility.isOnline(getActivity())) { // show lazy loading progress showLazyLoadingProgress(true); // run async task mLoadDataTask = new LoadDataTask(this); executeTask(mLoadDataTask); } } private void showLazyLoadingProgress(boolean visible) { if(visible) { mLazyLoading = true; // show footer if(mFooterList.size() <= 0) { mFooterList.add(new Object()); mAdapter.notifyItemInserted(mAdapter.getRecyclerPositionByFooter(0)); } } else { // hide footer if(mFooterList.size() > 0) { mFooterList.remove(0); mAdapter.notifyItemRemoved(mAdapter.getRecyclerPositionByFooter(0)); } mLazyLoading = false; } } private void bindData() { // reference RecyclerView recyclerView = getRecyclerView(); // content if(recyclerView.getAdapter() == null) { // create adapter mAdapter = new RecyclerAdapter(mHeaderList, mProductList, mFooterList, this); } else { // refill adapter mAdapter.refill(mHeaderList, mProductList, mFooterList, this); } // set fixed size recyclerView.setHasFixedSize(true); // add decoration RecyclerView.ItemDecoration itemDecoration = new LinearDividerItemDecoration(getActivity(), null); recyclerView.addItemDecoration(itemDecoration); // set animator recyclerView.setItemAnimator(new DefaultItemAnimator()); // set adapter recyclerView.setAdapter(mAdapter); // lazy loading recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); int firstVisibleItem = layoutManager.findFirstVisibleItemPosition(); int visibleItemCount = layoutManager.getChildCount(); int totalItemCount = layoutManager.getItemCount(); int lastVisibleItem = firstVisibleItem + visibleItemCount; if(totalItemCount - lastVisibleItem <= LAZY_LOADING_OFFSET && mProductList.size() % LAZY_LOADING_TAKE == 0 && !mProductList.isEmpty()) { if(!mLazyLoading) lazyLoadData(); } } }); } private void setupStatefulLayout(Bundle savedInstanceState) { // reference mStatefulLayout = (StatefulLayout) mRootView; // state change listener mStatefulLayout.setOnStateChangeListener(new StatefulLayout.OnStateChangeListener() { @Override public void onStateChange(View v, StatefulLayout.State state) { Logcat.d("" + (state == null ? "null" : state.toString())); if(state == StatefulLayout.State.CONTENT) { RecyclerView recyclerView = getRecyclerView(); if(mLazyLoading && recyclerView.getAdapter() != null) { mAdapter.notifyDataSetChanged(); } else { if(mProductList != null) bindData(); } } } }); // restore state mStatefulLayout.restoreInstanceState(savedInstanceState); } private RecyclerView getRecyclerView() { return mRootView != null ? (RecyclerView) mRootView.findViewById(R.id.fragment_recycler_recycler) : null; } private void setupRecyclerView() { LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity()); linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); RecyclerView recyclerView = getRecyclerView(); recyclerView.setLayoutManager(linearLayoutManager); // TODO: use LinearLayoutManager, GridLayoutManager or StaggeredGridLayoutManager } }