package jianshu.io.app.fragment; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.os.Parcelable; import android.support.v4.app.Fragment; import android.support.v4.widget.SwipeRefreshLayout; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; import net.tsz.afinal.FinalBitmap; import it.gmariotti.cardslib.library.internal.Card; import jianshu.io.app.R; import jianshu.io.app.adapter.TimeStreamCardArrayAdapter; import jianshu.io.app.card.CollectinUpdateCard; import jianshu.io.app.card.TimeStreamCard; import jianshu.io.app.card.UnknownUpdateCard; import jianshu.io.app.card.UserCommentCard; import jianshu.io.app.card.UserSubscribeCard; import jianshu.io.app.card.UserUpdateArticleCard; import jianshu.io.app.card.UserUpdateFollowCard; import jianshu.io.app.card.UserUpdateJoinCard; import jianshu.io.app.card.UserUpdateLikeCard; import jianshu.io.app.model.CollectionUpdateItem; import jianshu.io.app.model.JianshuSession; import jianshu.io.app.model.StatePool; import jianshu.io.app.model.UnknownUpdateItem; import jianshu.io.app.model.UpdateItem; import jianshu.io.app.model.UserCommentUpdateItem; import jianshu.io.app.model.UserSubscribeUpdateItem; import jianshu.io.app.model.UserUpdateArticleUpdateItem; import jianshu.io.app.model.UserUpdateFollowUpdateItem; import jianshu.io.app.model.UserUpdateJoinUpdateItem; import jianshu.io.app.model.UserUpdateLikeUpdateItem; import jianshu.io.app.model.datapool.DataPool; import jianshu.io.app.model.datapool.TimeStreamDataPool; import jianshu.io.app.util.DataPoolAsyncTask; import jianshu.io.app.widget.EndlessListener; import jianshu.io.app.widget.EndlessStaggeredGridView; import jianshu.io.app.widget.LoadingTextView; /** * A simple {@link Fragment} subclass. * Activities that contain this fragment must implement the * {@link TimeStreamFragment.OnFragmentInteractionListener} interface * to handle interaction events. * Use the {@link TimeStreamFragment#newInstance} factory method to * create an instance of this fragment. */ public class TimeStreamFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener, EndlessListener, TimeStreamCardArrayAdapter.CardClickListener { OnFragmentInteractionListener mListener; TimeStreamCardArrayAdapter mAdapter; EndlessStaggeredGridView mContentView; FinalBitmap mFb; boolean mIsEmpty; SwipeRefreshLayout mRefreshLayout; View mHeader; LoadingTextView mFooter; TimeStreamDataPool mPool; View mEmptyView; private static final String LIST_STATE = "listState"; Parcelable mListState; public static TimeStreamFragment newInstance() { TimeStreamFragment fragment = new TimeStreamFragment(); return fragment; } public TimeStreamFragment() { // Required empty public constructor } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_timestream, container, false); Activity activity = getActivity(); mFb = FinalBitmap.create(activity); Object[] states = StatePool.getInstance().getFragmentState(getActivity(), TimeStreamDataPool.TIMELINE_URL); mPool = (TimeStreamDataPool) states[0]; mAdapter = (TimeStreamCardArrayAdapter) states[1]; mAdapter.setCardClickListener(this); if (states[2] != null) { mListState = (Parcelable) states[2]; } mEmptyView = getActivity().getLayoutInflater().inflate(R.layout.empty_pull, null); mContentView = (EndlessStaggeredGridView) view.findViewById(R.id.timestream_grid); mContentView.setListener(this); mHeader = activity.getLayoutInflater().inflate(R.layout.header, null); mFooter = (LoadingTextView) activity.getLayoutInflater().inflate(R.layout.footer, null); mContentView.addHeaderView(mHeader); mContentView.setFooter(mFooter); mContentView.setAdapter(mAdapter); mRefreshLayout = (SwipeRefreshLayout) (view.findViewById(R.id.ptr_layout)); mRefreshLayout.setColorScheme(R.color.jianshu, R.color.card_list_gray, R.color.jianshu, R.color.card_list_gray); mRefreshLayout.setOnRefreshListener(this); return view; } @Override public void onViewStateRestored(Bundle savedInstanceState) { super.onViewStateRestored(savedInstanceState); if (mListState != null) { mContentView.onRestoreInstanceState(mListState); } } @Override public void onResume() { super.onResume(); //判断userInfo是否有变化 boolean isUserInfoChanged = true; String cachedSession = mAdapter.getSession(); String currentSession = JianshuSession.getsInstance().getSession(); if ((currentSession == null && cachedSession == null) || ((currentSession != null && cachedSession != null) && currentSession.equals(cachedSession))) { isUserInfoChanged = false; } mAdapter.setSession(currentSession); if (isUserInfoChanged || mAdapter.getCount() == 0) { mRefreshLayout.setRefreshing(true); onRefresh(); } else { mAdapter.notifyDataSetChanged(); } } @Override public void onPause() { super.onPause(); //如果第一个项目可见,那么恢复的时候将会跳到顶部,于是增加了一个1px的header解决这个BUG mListState = mContentView.onSaveInstanceState(); StatePool.getInstance().putListViewState(TimeStreamDataPool.TIMELINE_URL, mListState); } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mListener = (OnFragmentInteractionListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnFragmentInteractionListener"); } } @Override public void onDetach() { super.onDetach(); mListener = null; } @Override public void onRefresh() { new DataPoolAsyncTask(true, this.mPool, new DataPoolAsyncTask.OnPostExecuteTask() { @Override public void run(Exception exception, Object[] data) { mRefreshLayout.setRefreshing(false); Context context = getActivity(); if (context == null) { return; } if (exception != null) { if (exception instanceof DataPool.LoginRequiredException) { mListener.onLoginRequired(); Toast.makeText(context, "请重新登陆", Toast.LENGTH_LONG).show(); return; } } if (data != null) { if (mIsEmpty) { mIsEmpty = false; mRefreshLayout.removeView(mEmptyView); mRefreshLayout.addView(mContentView); } else { mAdapter.clear(); } mAdapter.addAll(initCard(context, data)); } else { if (context != null) { Toast.makeText(context, ":( 加载失败,请重试", Toast.LENGTH_LONG).show(); } if (mAdapter.getCount() == 0 && !mIsEmpty) { mIsEmpty = true; mRefreshLayout.removeView(mContentView); mRefreshLayout.addView(mEmptyView); } } } }).execute(); } private Card[] initCard(Context context, Object[] data) { int i = 0; Card[] result = new Card[data.length]; Card card; for (Object temp : data) { UpdateItem item = (UpdateItem) temp; if (item instanceof UserUpdateArticleUpdateItem) { card = new UserUpdateArticleCard(context, (UserUpdateArticleUpdateItem) item, mFb); } else if (item instanceof UserCommentUpdateItem) { card = new UserCommentCard(context, (UserCommentUpdateItem) item, mFb); } else if (item instanceof UserUpdateLikeUpdateItem) { card = new UserUpdateLikeCard(context, (UserUpdateLikeUpdateItem) item, mFb); } else if (item instanceof UserUpdateFollowUpdateItem) { card = new UserUpdateFollowCard(context, (UserUpdateFollowUpdateItem) item, mFb); } else if (item instanceof UserSubscribeUpdateItem) { card = new UserSubscribeCard(context, (UserSubscribeUpdateItem) item, mFb); } else if (item instanceof CollectionUpdateItem) { card = new CollectinUpdateCard(context, (CollectionUpdateItem) item, mFb); } else if(item instanceof UserUpdateJoinUpdateItem) { card = new UserUpdateJoinCard(context, (UserUpdateJoinUpdateItem) item, mFb); } else { card = new UnknownUpdateCard(context, (UnknownUpdateItem) item, mFb); } card.addPartialOnClickListener(Card.CLICK_LISTENER_CONTENT_VIEW, new Card.OnCardClickListener() { @Override public void onClick(Card card, View view) { mAdapter.onClick(card); } }); result[i++] = card; } return result; } @Override public boolean isAtTheEnd() { return mPool.isAtTheEnd(); } @Override public void onScrollEnd() { mFooter.startAnimation(); new DataPoolAsyncTask(false, this.mPool, new DataPoolAsyncTask.OnPostExecuteTask() { @Override public void run(Exception exception, Object[] data) { mFooter.endAnimation(); mContentView.notifyNewDataLoaded(); Context context = getActivity(); if (context == null) { return; } if (exception != null) { if (exception instanceof DataPool.LoginRequiredException) { mListener.onLoginRequired(); } } if (data != null) { mAdapter.addAll(initCard(context, data)); } else { Toast.makeText(context, ":( 加载失败,请重试", Toast.LENGTH_LONG).show(); } } }).execute(); } @Override public void onClick(Card card) { ((TimeStreamCard) card).onClick(getActivity()); } /** * This interface must be implemented by activities that contain this * fragment to allow an interaction in this fragment to be communicated * to the activity and potentially other fragments contained in that * activity. * <p/> * See the Android Training lesson <a href= * "http://developer.android.com/training/basics/fragments/communicating.html" * >Communicating with Other Fragments</a> for more information. */ public interface OnFragmentInteractionListener { public void onLoginRequired(); } }