com.umeng.comm.ui.fragments.BaseFeedsFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.umeng.comm.ui.fragments.BaseFeedsFragment.java

Source

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2014-2015 Umeng, Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package com.umeng.comm.ui.fragments;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.TranslateAnimation;
import android.view.inputmethod.InputMethodManager;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.umeng.comm.core.beans.CommConfig;
import com.umeng.comm.core.beans.CommUser;
import com.umeng.comm.core.beans.Comment;
import com.umeng.comm.core.beans.FeedItem;
import com.umeng.comm.core.beans.ForwardFeedItem;
import com.umeng.comm.core.beans.Like;
import com.umeng.comm.core.constants.Constants;
import com.umeng.comm.core.db.AbsDBHelper;
import com.umeng.comm.core.db.DbHelper;
import com.umeng.comm.core.db.DbHelperFactory;
import com.umeng.comm.core.db.cmd.DeleteCommand;
import com.umeng.comm.core.db.cmd.InsertCommand;
import com.umeng.comm.core.db.cmd.QueryCommand;
import com.umeng.comm.core.db.cmd.concrete.DbCommandFactory;
import com.umeng.comm.core.listeners.Listeners.CommListener;
import com.umeng.comm.core.listeners.Listeners.FetchListener;
import com.umeng.comm.core.listeners.Listeners.SimpleFetchListener;
import com.umeng.comm.core.nets.Response;
import com.umeng.comm.core.nets.responses.FeedsResponse;
import com.umeng.comm.core.nets.responses.LoginResponse;
import com.umeng.comm.core.nets.responses.SimpleResponse;
import com.umeng.comm.core.utils.CommonUtils;
import com.umeng.comm.core.utils.DeviceUtils;
import com.umeng.comm.core.utils.Log;
import com.umeng.comm.core.utils.ResFinder;
import com.umeng.comm.core.utils.SharePrefUtils;
import com.umeng.comm.core.utils.ToastMsg;
import com.umeng.comm.ui.activities.FindActivity;
import com.umeng.comm.ui.adapters.FeedAdapter;
import com.umeng.comm.ui.adapters.FeedAdapter.InitListener;
import com.umeng.comm.ui.adapters.viewparser.FeedItemViewParser.FeedItemViewHolder;
import com.umeng.comm.ui.broadcastreceiver.NotifyBroadcastReceiver;
import com.umeng.comm.ui.broadcastreceiver.NotifyBroadcastReceiver.NotifyListener;
import com.umeng.comm.ui.broadcastreceiver.UserInfoNotifyListener;
import com.umeng.comm.ui.dialogs.ConfirmDialog;
import com.umeng.comm.ui.utils.Filter;
import com.umeng.comm.ui.utils.ViewFinder;
import com.umeng.comm.ui.widgets.CommentEditText;
import com.umeng.comm.ui.widgets.CommentEditText.EditTextBackEventListener;
import com.umeng.comm.ui.widgets.RefreshLayout.OnLoadListener;
import com.umeng.comm.ui.widgets.RefreshLvLayout;
import com.umeng.comm.ui.widgets.WrapperListView;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * ???,FeedDetailFragment(
 * ??feed)???.???????????????????.
 * ?.
 * 
 * @author mrsimple
 */
public abstract class BaseFeedsFragment extends FeedDetailFragment {

    /**
     * , , Feeds ListView
     */
    protected RefreshLvLayout mRefreshLayout;
    /**
     * feeds ListView
     */
    protected ListView mFeedsListView;

    /**
     * ???
     */
    protected FeedAdapter mFeedLvAdapter;

    /**
     * 
     */
    public CommentEditText mCommentEditText;
    /**
     * 
     */
    protected View mCommentLayout;

    /**
     * titleTextView
     */
    protected TextView mTitleTextView;

    /**
     * ListViewfooters
     */
    protected List<View> mFooterViews = new ArrayList<View>();

    /**
     * ?OnGlobalLayoutListener???????listview
     */
    private boolean isShowKeyboard = false;

    /**
     * ?filter
     */
    protected Filter<FeedItem> mFeedFilter;

    /**
     * ????????
     */
    private OnGlobalLayoutListener mOnGlobalLayoutListener;
    /**
     * feed like?top and bottom padding
     */
    private int mLikeItemPadding = 0;

    /**
     * 
     */
    protected CommUser mUser = CommConfig.getConfig().loginedUser;

    /**
     * ?
     */
    NotifyBroadcastReceiver mUserBroadcastReceiver;
    /**
     * feed??
     */
    NotifyBroadcastReceiver mPostBroadcastReceiver;

    /**
     * ?
     */
    protected NotifyBroadcastReceiver mBroadcastReceiver;
    /**
     * ????
     */
    protected AtomicBoolean isNeedRemoveOldFeeds = new AtomicBoolean(true);

    protected String mNextPageUrl = "";

    private boolean hasRefresh = false;

    private int totalTime = 0;
    private boolean isFinish = false;
    private InputMethodManager mInputMan;
    private int mSlop;

    List<String> mTabTitls = new ArrayList<String>();
    /**
     * ?feedbutton
     */
    protected ImageView mPostBtn;

    /**
     * button
     */
    protected ImageView mLocationBtn;

    /**
     * Handler????
     */
    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            View view = (View) msg.obj;
            // 
            if (msg.what == Constants.INPUT_METHOD_SHOW) {
                boolean result = mInputMan.showSoftInput(view, 0);
                if (!result && totalTime < Constants.LIMIT_TIME) {
                    totalTime += Constants.IDLE;
                    Message message = Message.obtain(msg);
                    mHandler.sendMessageDelayed(message, Constants.IDLE);
                } else if (!isFinish) {
                    totalTime = 0;
                    result = view.requestFocus();
                    isFinish = true;
                }
            } else if (msg.what == Constants.INPUT_METHOD_DISAPPEAR) {
                // ??
                mInputMan.hideSoftInputFromWindow(view.getWindowToken(), 0);
            }

        }
    };

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        mRootView = inflater.inflate(ResFinder.getLayout("umeng_comm_feeds_frgm_layout"), container, false);
        mInputMan = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);

        // ?
        initViews();
        // ?ActionButtonlike?????Dialog View
        initWidgets();
        // ?Feed Adapter
        initAdapter();
        // 
        registerBroadcast();
        // cache??
        loadFeedsFromDB();
        // ?
        mRefreshLayout.setRefreshing(true);
        // server??
        fetchFeeds();
        mSlop = ViewConfiguration.get(container.getContext()).getScaledTouchSlop();
        return mRootView;
    }

    /**
     * ?feed? ?View
     */
    protected void initViews() {
        mViewFinder = new ViewFinder(mRootView);

        // ?View
        initRefreshView();
        // ?Title View
        // initTitleView();
        // ?
        initCommentView();
        mPostBtn = mViewFinder.findViewById(ResFinder.getId("umeng_comm_new_post_btn"));
        mLocationBtn = mViewFinder.findViewById(ResFinder.getId("umeng_comm_new_location_btn"));
    }

    /**
     * ?, listview
     */
    private void initRefreshView() {
        // , 
        mRefreshLayout = mViewFinder.findViewById(ResFinder.getId("umeng_comm_swipe_layout"));

        // 
        mRefreshLayout.setOnRefreshListener(new OnRefreshListener() {

            @Override
            public void onRefresh() {
                // feed
                fetchFeeds();
            }
        });

        // 
        mRefreshLayout.setOnLoadListener(new OnLoadListener() {

            @Override
            public void onLoad() {
                loadMoreFeed();
            }
        });

        // ?, ??
        mRefreshLayout.addOnScrollListener(new OnScrollListener() {

            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
                    mImageLoader.resume();
                } else {
                    mImageLoader.pause();
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

            }
        });

        int feedListViewResId = ResFinder.getId("umeng_comm_feed_listview");
        // feed listview
        mFeedsListView = mRefreshLayout.findRefreshViewById(feedListViewResId);
        // footer
        mRefreshLayout.setDefaultFooterView();
        // 
        mFeedsListView.setAnimationCacheEnabled(false);
        // ?smooth scrool bar
        mFeedsListView.setSmoothScrollbarEnabled(true);
        // EditTexttouchListviewLayout?????
        mFeedsListView.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (mCommentLayout.isShown()) {
                    hideCommentLayoutAndInputMethod();
                    return true;
                }
                return false;
            }
        });

        mFeedsListView.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                checkWhetherExecuteAnimation(event);
                if (mCommentLayout.isShown()) {
                    hideCommentLayoutAndInputMethod();
                    return true;
                }
                return false;
            }
        });
    }

    private int mLastScrollY = 0;// Y??
    private static final int STATUS_NORMAL = 0x01;// ??
    private static final int STATUS_SHOW = 0x02;// ?
    private static final int STATUS_DISMISS = 0x03;// ???
    private transient int currentStatus = STATUS_NORMAL; // ?Float Button?
    private transient boolean isExecutingAnim = false; // ?

    /**
     * ?Float button</br>
     * 
     * @param event
     */
    private void checkWhetherExecuteAnimation(MotionEvent event) {
        int y = (int) event.getY();
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            mLastScrollY = y;
            break;
        case MotionEvent.ACTION_MOVE:
            int deltaY = mLastScrollY - y;
            mLastScrollY = y;
            if (Math.abs(deltaY) < mSlop) {
                return;
            }
            if (deltaY > 0) {
                executeAnimation(false);
            } else {
                executeAnimation(true);
            }
            break;
        default:
            break;
        }
    }

    /**
     * Float button</br>
     * 
     * @param show  or ?
     */
    private void executeAnimation(final boolean show) {
        if (isExecutingAnim || (show && currentStatus == STATUS_SHOW)
                || (!show && currentStatus == STATUS_DISMISS)) {
            return;
        }
        isExecutingAnim = true;
        int moveDis = ((FrameLayout.LayoutParams) (mPostBtn.getLayoutParams())).bottomMargin + mPostBtn.getHeight();
        Animation animation = null;
        if (show) {
            animation = new TranslateAnimation(0, 0, moveDis, 0);
        } else {
            animation = new TranslateAnimation(0, 0, 0, moveDis);
        }
        animation.setDuration(300);
        animation.setFillAfter(true);
        animation.setAnimationListener(new AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                isExecutingAnim = false;
                if (show) {
                    currentStatus = STATUS_SHOW;
                } else {
                    currentStatus = STATUS_DISMISS;
                }
                // 3.0???????Float
                // Button?layout?
                mPostBtn.setClickable(show);
            }
        });
        mPostBtn.startAnimation(animation);
    }

    /**
     * ??</br>
     */
    public void hideCommentLayoutAndInputMethod() {
        resetCommentLayout();
        hideInputMethod();
        showPostButtonWithAnim();
    }

    /**
     * </br>
     */
    private void showInputMethod() {
        sendInputMethodMessage(Constants.INPUT_METHOD_SHOW, mCommentEditText);
    }

    /**
     * </br>
     */
    private void hideInputMethod() {
        if (CommonUtils.isActivityAlive(getActivity())) {
            sendInputMethodMessage(Constants.INPUT_METHOD_DISAPPEAR, mCommentEditText);
            mRootView.getViewTreeObserver().removeGlobalOnLayoutListener(mOnGlobalLayoutListener);
        }
    }

    /**
     * 
     */
    protected void showPostButtonWithAnim() {
    }

    /**
     * 
     */
    private void hidePostButtonWithAnim() {
        AlphaAnimation animation = new AlphaAnimation(1.0f, 0f);
        animation.setDuration(500);

        mPostBtn.setVisibility(View.GONE);
        mPostBtn.startAnimation(animation);
    }

    @Override
    protected void initButtonsClickListener(FeedItemViewHolder viewHolder, final FeedItem feedItem, int position) {
        super.initButtonsClickListener(viewHolder, feedItem, position);

        viewHolder.mDialogButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                mCurFeedItem = feedItem;
                showSelectDialog();
            }
        });
    }

    @Override
    protected FeedItem findFeedWithId(String feedId) {

        if (mCurFeedItem.id.equals(feedId)) {
            return mCurFeedItem;
        }

        List<FeedItem> allFeedItems = mFeedLvAdapter.getDataSource();
        for (FeedItem feedItem : allFeedItems) {
            if (feedId.equals(feedItem.id)) {
                return feedItem;
            }
        }

        return new FeedItem();
    }

    private String[] prepareMenus() {
        String[] menus = null;
        if (isMyFeed(mCurFeedItem)) {
            menus = new String[] { ResFinder.getString("umeng_comm_delete_feed_tips") };
        } else {
            menus = new String[] { ResFinder.getString("umeng_comm_report_feed_tips") };
        }

        return menus;
    }

    private void showSelectDialog() {
        AlertDialog.Builder dBuilder = new AlertDialog.Builder(getActivity());
        final String[] menus = prepareMenus();
        dBuilder.setItems(menus, new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, final int which) {
                dialog.dismiss();

                final String msg = menus[which] + ResFinder.getString("umeng_comm_this_feed");
                showOprationDialog(msg, which);

            }
        });
        dBuilder.create().show();
    }

    private void showOprationDialog(String msg, final int which) {
        ConfirmDialog.showDialog(getActivity(), msg, new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int invalid) {
                // feed
                if (which == 0 && isMyFeed(mCurFeedItem) && isDeletable(mCurFeedItem)) {
                    deleteCurrentFeed();
                } else if (which != -1) {
                    reportCurrentFeed();
                }
            }
        });
    }

    /**
     * ?feed????Toast?? feed0???{@link FeedItem}
     * satus</br>
     * 
     * @param item
     * @return
     */
    private boolean isDeletable(FeedItem item) {
        if (item.status <= FeedItem.STATUS_VOTED) {
            return true;
        }
        ToastMsg.showShortMsgByResName(getActivity(), "umeng_comm_user_name_feed_invalid");
        return false;
    }

    @Override
    protected void deleteInvalidateFeed(FeedItem feedItem) {
        super.deleteInvalidateFeed(feedItem);
        // feedlistview
        mFeedLvAdapter.getDataSource().remove(feedItem);
        mFeedLvAdapter.notifyDataSetChanged();
    }

    /**
     * server?feed</br>
     */
    private void deleteCurrentFeed() {
        mSdkImpl.deleteFeed(mCurFeedItem.id, new CommListener() {

            @Override
            public void onStart() {
            }

            @Override
            public void onComplete(Response data) {
                // ??
                if (data.errCode == Constants.USER_FORBIDDEN_ERR_CODE) {
                    ToastMsg.showShortMsg(getActivity(), ResFinder.getString("umeng_comm_user_unusable"));
                    return;
                }

                if (data.errCode == 0) {
                    updateAfterDelete(mCurFeedItem);
                    deleteFeedFromDB();
                }

                final String toast = data.errCode == 0 ? ResFinder.getString("umeng_comm_delete_success")
                        : ResFinder.getString("umeng_comm_delete_failed");
                ToastMsg.showShortMsg(getActivity(), toast);
            }
        });
    }

    protected void updateAfterDelete(FeedItem feedItem) {
        mFeedLvAdapter.getDataSource().remove(feedItem);
        mFeedLvAdapter.notifyDataSetChanged();

        // ??
        sendDeleteFeedBrocast(feedItem);
    }

    private void sendDeleteFeedBrocast(FeedItem feedItem) {
        Intent intent = new Intent(NotifyBroadcastReceiver.FEED_DELETED);
        intent.putExtra(Constants.FEED, feedItem);
        getActivity().sendBroadcast(intent);
    }

    /**
     * ?feed</br>
     */
    private void deleteFeedFromDB() {
        Map<String, String> wheres = new HashMap<String, String>();
        wheres.put(AbsDBHelper.ID, mCurFeedItem.id);
        // 
        DbHelper<FeedItem> helper = DbHelperFactory.getFeedDbHelper(getActivity());
        DeleteCommand<FeedItem> deleteCommand = new DeleteCommand<FeedItem>(helper, wheres);
        helper.setOnItemFetchedListener(null);
        deleteCommand.execute();
    }

    private void reportCurrentFeed() {

        SimpleFetchListener<LoginResponse> loginListener = new SimpleFetchListener<LoginResponse>() {
            @Override
            public void onComplete(LoginResponse response) {
                if (response.errCode == Constants.NO_ERROR) {
                    // feed
                    mSdkImpl.spammerFeed(mCurFeedItem.id, new FetchListener<SimpleResponse>() {

                        @Override
                        public void onStart() {
                        }

                        @Override
                        public void onComplete(SimpleResponse response) {
                            if (response.errCode == Constants.NO_ERROR) {
                                ToastMsg.showShortMsgByResName(getActivity(), "umeng_comm_text_spammer_success");
                            } else if (response.errCode == Constants.SPAMMERED_CODE) {
                                ToastMsg.showShortMsgByResName(getActivity(), "umeng_comm_text_spammered");
                            } else {
                                ToastMsg.showShortMsgByResName(getActivity(), "umeng_comm_text_spammer_failed");
                            }
                        }
                    });
                }
            }
        };
        CommonUtils.checkLoginAndFireCallback(getActivity(), loginListener);

    }

    /**
     * 
     */
    private void initCommentView() {
        int commentLayoutResId = ResFinder.getId("umeng_comm_commnet_edit_layout");
        // 
        mCommentLayout = mRootView.findViewById(commentLayoutResId);
        int commentEditTextResId = ResFinder.getId("umeng_comm_comment_edittext");
        mCommentEditText = mViewFinder.findViewById(commentEditTextResId);
        mCommentEditText.setEditTextBackListener(new EditTextBackEventListener() {

            @Override
            public void onClickBack() {
                // mCommentLayout.setVisibility(View.INVISIBLE);
                resetCommentLayout();
                showPostButtonWithAnim();
            }
        });

        int sendButtonId = ResFinder.getId("umeng_comm_comment_send_button");
        // ?
        mRootView.findViewById(sendButtonId).setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                final String commentText = mCommentEditText.getText().toString();
                boolean result = checkCommentData(commentText);
                if (result) {
                    postComment(commentText, mPostCommentListener);
                } else {
                    ToastMsg.showShortMsgByResName(getActivity(), "umeng_comm_content_invalid");
                }
            }
        });

    }

    /**
     * feed?feed</br>
     * 
     * @param feedItems feed
     * @return
     */
    private List<FeedItem> getNewFeedItems(List<FeedItem> feedItems) {
        List<FeedItem> notExsitFeeds = removeExsitItems(mFeedLvAdapter.getDataSource(), feedItems);
        // ?
        return filteFeeds(notExsitFeeds);
    }

    /**
     * ?adapter?,?</br>
     * 
     * @param feedItems
     */
    protected void addFeedItemsToHeader(List<FeedItem> feedItems) {
        feedItems = removeSpamFeed(feedItems);
        List<FeedItem> olds = mFeedLvAdapter.getDataSource();
        olds.removeAll(feedItems);
        olds.addAll(0, feedItems);
        // feedfeed????????feed??
        Collections.sort(olds, mComparator);
        mFeedLvAdapter.notifyDataSetChanged();
    }

    /**
     * ?adapter?,??</br>
     * 
     * @param feedItems
     */
    protected List<FeedItem> appendFeedItems(List<FeedItem> feedItems) {
        List<FeedItem> newFeeds = getNewFeedItems(feedItems);
        // listview
        mFeedLvAdapter.addData(newFeeds);
        return newFeeds;
    }

    /**
     * ???
     */
    private CommListener mPostCommentListener = new CommListener() {

        @Override
        public void onStart() {
            hideCommentLayoutAndInputMethod();
        }

        @Override
        public void onComplete(Response resp) {
            if (resp.errCode == Constants.NO_ERROR) {
                resetCommentLayout();
                // // feedlistviewlistviewviewstub inflate?
                // // ?
                // mCommentListView.setVisibility(View.VISIBLE);
            }
        }
    };

    @Override
    protected void savePostedComment(Comment comment, String commId) {
        mCommentEditText.setText("");
        super.savePostedComment(comment, commId);
    }

    /**
     *  [ ???? ]
     * 
     * @param oldItems ?listview?
     * @param newItems ??
     * @return
     */
    protected <T> List<T> removeExsitItems(List<T> oldItems, List<T> newItems) {
        // ?feeds
        oldItems.removeAll(newItems);
        return newItems;
    }

    protected void parseNextpageUrl(List<FeedItem> items, boolean fromRefersh) {
        if (items == null || items.size() == 0) {
            return;
        }
        if (fromRefersh && TextUtils.isEmpty(mNextPageUrl) && !hasRefresh) {
            hasRefresh = true;
            mNextPageUrl = items.get(0).nextPageUrl;
        } else if (!fromRefersh) {
            mNextPageUrl = items.get(items.size() - 1).nextPageUrl;
        }
    }

    /**
     * ?</br>
     */
    protected void loadMoreFeed() {

        // ?
        if (!DeviceUtils.isNetworkAvailable(getActivity())) {
            loadFeedsFromDB();
            return;
        }

        if (TextUtils.isEmpty(mNextPageUrl)) {
            ToastMsg.showShortMsgByResName(getActivity(), "umeng_comm_text_load_over");
            mRefreshLayout.setLoading(false);
            return;
        }
        mSdkImpl.fetchNextPageData(mNextPageUrl, FeedsResponse.class, new SimpleFetchListener<FeedsResponse>() {

            @Override
            public void onComplete(FeedsResponse response) {
                mRefreshLayout.setLoading(false);
                Log.d(getTag(), "### ? : " + response.result.size());

                // ?responseToast
                if (handlerResponse(response)) {
                    return;
                }
                parseNextpageUrl(response.result, false);
                // ??feed
                final List<FeedItem> feedItems = filteFeeds(response.result);
                if (feedItems != null && feedItems.size() > 0) {
                    removeSpamFeed(feedItems);
                    // ?
                    appendFeedItems(feedItems);
                    saveFeedsToDB(feedItems);
                }
            }
        });
    }

    /**
     * >=2feed</br>
     * 
     * @param items
     * @return
     */
    protected List<FeedItem> removeSpamFeed(List<FeedItem> items) {
        Iterator<FeedItem> iterator = items.iterator();
        while (iterator.hasNext()) {
            FeedItem item = iterator.next();
            if (item.status >= 2) {
                iterator.remove();
            }
        }
        return items;
    }

    /**
     * cache?</br>
     */
    protected void loadFeedsFromDB() {
        // ?
        if (CommonUtils.isActivityAlive(getActivity())
        /* && !TextUtils.isEmpty(mUser.id) */) {
            executeLoadFeedsCommand();
        } else {
            mRefreshLayout.setLoading(false);
        }
    }

    /**
     * ?feed
     */
    protected void executeLoadFeedsCommand() {
        // ,?feed
        QueryCommand<FeedItem> feedQueryCommand = DbCommandFactory.createQueryFeedCmd(getActivity(), mUser.id,
                mFeedLvAdapter.getCount());
        // ?ListView,????
        feedQueryCommand.setOnItemFetchedListener(new SimpleFetchListener<FeedItem>() {
            @Override
            public void onComplete(FeedItem response) {
                if (CommonUtils.isActivityAlive(getActivity())) {
                    dealFeedData(response);
                    if (mImageLoader != null) {
                        mImageLoader.resume();
                    }
                }
            }
        });
        // ?
        feedQueryCommand.setFetchListener(new SimpleFetchListener<List<FeedItem>>() {

            @Override
            public void onComplete(List<FeedItem> response) {
                mRefreshLayout.setLoading(false);
            }
        });
        feedQueryCommand.execute();
    }

    /**
     * feed??</br>
     * 
     * @param data
     */
    protected void dealFeedData(FeedItem data) {
        List<FeedItem> items = new ArrayList<FeedItem>();
        items.add(data);
        items = getNewFeedItems(items);
        if (items.size() > 0) {
            // ?Listview
            addNewFeed(items.get(0));
        }
    }

    /**
     * feedlistview. [ ???? ]
     * 
     * @param feedItem
     */
    protected void addNewFeed(FeedItem feedItem) {
        final List<FeedItem> lists = mFeedLvAdapter.getDataSource();
        lists.add(feedItem);
        Collections.sort(lists, mComparator);
        mFeedLvAdapter.updateListViewData(lists);
    }

    protected Comparator<FeedItem> mComparator = new Comparator<FeedItem>() {

        @Override
        public int compare(FeedItem lhs, FeedItem rhs) {
            return rhs.publishTime.compareTo(lhs.publishTime);
        }
    };

    /**
     * ??
     */
    public void initAdapter() {
        if (mFeedLvAdapter == null) {
            mFeedLvAdapter = new FeedAdapter(getActivity(), new ArrayList<FeedItem>());
        }
        mFeedLvAdapter.setInitItemListener(new InitListener() {

            @Override
            public void initItem(View rootView, final FeedItemViewHolder holder, final int position) {
                // likepaddingitem
                calculateLikePadding(holder.mLikeView);
                // get FeedItem at position
                final FeedItem feedItem = mFeedLvAdapter.getItem(position);
                // ?
                setFeedItemData(rootView, feedItem, position);
                // ?
                initButtonsClickListener(holder, feedItem, position);
            }
        });
        mFeedsListView.setAdapter(mFeedLvAdapter);
    }

    private void calculateLikePadding(View likeView) {
        if (mLikeItemPadding == 0) {
            mLikeItemPadding = likeView.getPaddingBottom() + likeView.getPaddingTop();
        }
    }

    // /**
    // * ??Title 
    // */
    // protected void initTitleView() {
    // int titleLayoutResId = ResFinder.getId("topic_action_bar");
    // mTitleLayout = mRootView.findViewById(titleLayoutResId);
    // mTitleLayout.setVisibility(View.GONE);
    //
    // //
    // mProfileBtn =
    // mViewFinder.findViewById(ResFinder.getId("umeng_comm_user_info_btn"));
    // mProfileBtn.setOnClickListener(new OnClickListener() {
    //
    // @Override
    // public void onClick(View v) {
    // // gotoUserInfoActivity(CommConfig.getConfig().loginedUser);
    // gotoFindActivity(CommConfig.getConfig().loginedUser);
    // }
    // });
    //
    // mPostBtn =
    // mViewFinder.findViewById(ResFinder.getId("umeng_comm_new_post_btn"));
    //
    // mTabTitls.add("");
    // // mTabTitls.add("?");
    // mTabTitls.add("??");
    //
    // SlidingTextView textView =
    // mViewFinder.findViewById(ResFinder.getId("umeng_comm_title_tv"));
    // // TextView textView =
    // mViewFinder.findViewById(ResFinder.getId("umeng_comm_title_tv"));
    // textView.setSlidingAdapter(new SlidingAdapter() {
    //
    // @Override
    // public String getTitle(int position) {
    // return mTabTitls.get(position);
    // }
    //
    // @Override
    // public int getCount() {
    // return mTabTitls.size();
    // }
    // });
    // textView.setOnIndexChangeListener(new OnIndexChangeListener() {
    //
    // @Override
    // public void onChange(int oldIndex, int index) {
    // Log.d(getTag(), "### old index = " + oldIndex + ", new index " + index);
    // backData(oldIndex);
    // fetchNewFeedsWithIndex(index);
    // }
    // });
    // }

    // /**
    // * @param index
    // */
    // private void backData(int oldIndex) {
    // if (oldIndex == 0) {
    // mMainFeedList = mFeedLvAdapter.getDataSource();
    // } else if (oldIndex == 1) {
    // mMomentsFeedList = mFeedLvAdapter.getDataSource();
    // } else {
    // mRecommendFeedList = mFeedLvAdapter.getDataSource();
    // }
    // }

    // private void fetchNewFeedsWithIndex(int newIndex) {
    // if (newIndex == 0) {
    // mFeedLvAdapter.addData(mMainFeedList);
    // fetchFeeds();
    // }
    // // else if (newIndex == 1) {
    // // mFeedLvAdapter.addData(mMomentsFeedList);
    // // fetchMomentsFeeds();
    // // }
    // else {
    // mFeedLvAdapter.addData(mRecommendFeedList);
    // fetchRecomendedFeeds();
    // }
    // }

    // /**
    // * ??feed?
    // */
    // private void fetchMomentsFeeds() {
    //
    // }

    /**
     * ?Activity</br>
     * 
     * @param user
     */
    public void gotoFindActivity(final CommUser user) {
        CommonUtils.checkLoginAndFireCallback(getActivity(), new SimpleFetchListener<LoginResponse>() {

            @Override
            public void onComplete(LoginResponse response) {
                Intent intent = new Intent(getActivity(), FindActivity.class);
                if (user == null) {// ??
                    intent.putExtra(Constants.TAG_USER, CommConfig.getConfig().loginedUser);
                } else {
                    intent.putExtra(Constants.TAG_USER, user);
                }
                intent.putExtra(Constants.TYPE_CLASS, mContainerClass);
                getActivity().startActivity(intent);
            }
        });
    }

    @Override
    public void onResume() {
        super.onResume();
        mFeedsListView.postDelayed(new Runnable() {

            @Override
            public void run() {
                hideInputMethod();
                if (mImageLoader != null) {
                    // ??
                    mImageLoader.resume();
                }
            }
        }, 300);

        //
        registerPostNotifyReceiver();
        //
        registerUserInfoReceiver();
        //
        removeDeletedFeeds();
    }

    public void onStop() {
        resetCommentLayout();
        super.onStop();
    }

    NotifyListener mPostedNotifyListener = new NotifyListener() {

        @Override
        public void onNotify(Intent intent) {
            mFeedsListView.scrollTo(0, 0);
            mFeedsListView.invalidate();
            fetchFeeds();
        }
    };

    protected boolean isMyPage(FeedItem feedItem) {
        return feedItem != null;
    }

    /**
     * ??feed</br>
     */
    protected void registerBroadcast() {
        mBroadcastReceiver = new NotifyBroadcastReceiver(new NotifyListener() {

            @Override
            public void onNotify(Intent intent) {
                CommUser user = intent.getExtras().getParcelable(Constants.USER);
                List<FeedItem> items = mFeedLvAdapter.getDataSource();
                List<FeedItem> scrapItems = new ArrayList<FeedItem>();
                for (FeedItem item : items) {
                    if (item.creator.equals(user)) {
                        scrapItems.add(item);
                    }
                }
                if (scrapItems.size() > 0) {
                    mFeedLvAdapter.getDataSource().removeAll(scrapItems);
                    mFeedLvAdapter.notifyDataSetChanged();
                }
            }
        });

        IntentFilter intentFilter = new IntentFilter(NotifyBroadcastReceiver.CANCEL_FOLLOWED);
        getActivity().registerReceiver(mBroadcastReceiver, intentFilter);
    }

    protected void registerPostNotifyReceiver() {
        if (mPostBroadcastReceiver == null) {
            mPostBroadcastReceiver = new NotifyBroadcastReceiver(new NotifyListener() {

                @Override
                public void onNotify(Intent intent) {
                    FeedItem feedItem = intent.getExtras().getParcelable(Constants.FEED);
                    if (!isMyPage(feedItem)) {
                        return;
                    }
                    final String action = intent.getAction();
                    if (action.equals(NotifyBroadcastReceiver.FEED_POSTED)) {
                        Log.d(getTag(), "### feed : " + feedItem);
                        mFeedLvAdapter.addToFirst(feedItem);
                        mFeedsListView.setSelection(0);
                        // [???feed??feed]
                        // fetchFeeds();
                    } else if (action.equals(NotifyBroadcastReceiver.FEED_DELETED)) {
                        if (feedItem != null) {
                            mFeedLvAdapter.getDataSource().remove(feedItem);
                            mFeedLvAdapter.notifyDataSetChanged();
                            Log.d(getTag(), "### feed");
                        }
                    }

                    mFeedsListView.invalidate();
                }
            });

            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(NotifyBroadcastReceiver.FEED_POSTED);
            intentFilter.addAction(NotifyBroadcastReceiver.FEED_DELETED);
            // post
            getActivity().registerReceiver(mPostBroadcastReceiver, intentFilter);
        }
    }

    NotifyListener mUserInfoListener = new UserInfoNotifyListener() {

        @Override
        public void onNotify(Intent intent) {
            CommUser user = newUser(intent);
            if (user != null) {
                mUser = user;
                updatedUserInfo(mUser);
            }
        }
    };

    /**
     * 
     */
    private void registerUserInfoReceiver() {
        if (mUserBroadcastReceiver == null) {
            mUserBroadcastReceiver = new NotifyBroadcastReceiver(mUserInfoListener);
            getActivity().registerReceiver(mUserBroadcastReceiver,
                    new IntentFilter(NotifyBroadcastReceiver.USER_INFO_UPDATED));
        }
    }

    /**
     * Feed???</br>
     * 
     * @param feedItem
     * @return
     */
    protected boolean isMyFeed(FeedItem feedItem) {
        CommUser user = CommConfig.getConfig().loginedUser;
        if (user == null || TextUtils.isEmpty(user.id)) {
            return false;
        }
        return feedItem.creator.id.equals(user.id);
    }

    /**
     * ??feed?
     * 
     * @param user
     */
    public void updatedUserInfo(CommUser user) {
        mUser = user;
        List<FeedItem> feedItems = mFeedLvAdapter.getDataSource();
        for (FeedItem feed : feedItems) {
            updateFeedDetail(feed, user);
        }

        mFeedLvAdapter.notifyDataSetChanged();
    }

    private void updateFeedDetail(FeedItem feed, CommUser user) {
        if (isMyFeed(feed)) {
            feed.creator = user;
            Log.d(getTag(), " : " + user.name);
        }

        // like?
        updateLikeCreator(feed.likes, user);
        // ?
        updateCommentCreator(feed.comments, user);
        // at?creator
        updateAtFriendCreator(feed.atFriends, user);
        // ?feed
        if (feed instanceof ForwardFeedItem) {
            updateFeedDetail(((ForwardFeedItem) feed).forwardItem, user);
        }
    }

    private void updateLikeCreator(List<Like> likes, CommUser user) {
        for (Like likeItem : likes) {
            if (likeItem.creator.id.equals(user.id)) {
                likeItem.creator = user;
            }
        }
    }

    private void updateCommentCreator(List<Comment> comments, CommUser user) {
        for (Comment commentItem : comments) {
            if (commentItem.creator.id.equals(user.id)) {
                commentItem.creator = user;
            }
        }
    }

    private void updateAtFriendCreator(List<CommUser> friends, CommUser user) {
        for (CommUser item : friends) {
            if (item.id.equals(user.id)) {
                item = user;
            }
        }
    }

    /**
     * feed?,Feed??ListView?.feedSharedPreferences?.
     */
    private void removeDeletedFeeds() {
        SharedPreferences deletedSharedPref = SharePrefUtils.getSharePrefEdit(getActivity(),
                Constants.DELETED_FEEDS_PREF);
        // all deleted feeds iterator.
        Iterator<String> deletedIterator = deletedSharedPref.getAll().keySet().iterator();
        // ???feed
        while (deletedIterator.hasNext()) {
            String feedId = deletedIterator.next();
            //
            Iterator<FeedItem> feedIterator = mFeedLvAdapter.getDataSource().iterator();
            // find the target feed
            while (feedIterator.hasNext()) {
                FeedItem feedItem = feedIterator.next();
                if (feedItem.id.equals(feedId)) {
                    feedIterator.remove();
                    break;
                }
            } // end of second while
        } // first while

        mFeedLvAdapter.notifyDataSetChanged();
        deletedSharedPref.edit().clear();
    }

    /**
     * feed</br>
     * 
     * @param filter
     */
    public void setFeedFilter(Filter<FeedItem> filter) {
        mFeedFilter = filter;
    }

    /**
     * ?FeedListView</br>
     * 
     * @return
     */
    public ListView getListView() {
        return mFeedsListView;
    }

    /**
     * ?</br>
     * 
     * @return
     */
    protected List<FeedItem> filteFeeds(List<FeedItem> list) {
        List<FeedItem> destList = mFeedFilter != null ? mFeedFilter.doFilte(list) : list;
        // status>=2feed??
        Iterator<FeedItem> iterator = destList.iterator();
        while (iterator.hasNext()) {
            FeedItem item = iterator.next();
            if (item.status > 1) {
                iterator.remove();
            }
        }
        return destList;
    }

    /**
     * Server?feed
     */
    protected abstract void fetchFeeds();

    /**
     * ???DB???Insert?.
     * 
     * @param newFeedItems
     */
    protected void saveFeedsToDB(final List<FeedItem> newFeedItems) {
        DbHelper<FeedItem> helper = DbHelperFactory.getFeedDbHelper(getActivity());
        InsertCommand<FeedItem> insertCommand = new InsertCommand<FeedItem>(helper, newFeedItems);
        insertCommand.execute();
    }

    /**
     * ??</br>
     * 
     * @param content 
     * @return
     */
    private boolean checkCommentData(String content) {
        // ??
        if (TextUtils.isEmpty(content)) {
            ToastMsg.showShortMsgByResName(getActivity(), "umeng_comm_content_invalid");
            return false;
        }
        return true;
    }

    /**
     * ????
     */
    private void performListenKeyboard() {
        if (mOnGlobalLayoutListener == null) {
            mOnGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {

                    final int screenHeight = mRootView.getRootView().getHeight();
                    int keyboardHeight = screenHeight - mRootView.getHeight();
                    // ??1/3?
                    if (keyboardHeight < screenHeight / 3 || !isShowKeyboard) {
                        return;
                    }
                    // ?
                    isShowKeyboard = false;
                    final int[] layoutSize = new int[2];
                    mCommentLayout.getLocationOnScreen(layoutSize);
                    mFeedsListView.post(new Runnable() {

                        @Override
                        public void run() {
                            int dis = 0;
                            dis = layoutSize[1] + mScrollDis;
                            if (mCommentListView != null) {
                                dis -= mCommentListView.getPaddingBottom() + mCommentListView.getPaddingTop();
                            }
                            if (mClickItemView != null) {
                                dis -= mClickItemView.getHeight();
                            }
                            mFeedsListView.setSelectionFromTop(
                                    mCurFeedItemIndex + mFeedsListView.getHeaderViewsCount(), dis);
                        }
                    });
                }
            };
        }
        // GlobalLayoutListener
        mRootView.getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener);
    }

    /*
     * 
     */
    @Override
    protected void showCommentLayout(final int pos, boolean fromClickBtn) {

        mRootView.post(new Runnable() {

            @Override
            public void run() {
                mCommentLayout.setVisibility(View.VISIBLE);
                if (mCommentEditText.requestFocus()) {
                    // 
                    showInputMethod();
                }
                isShowKeyboard = true;
                performListenKeyboard();
                hidePostButtonWithAnim();
                // getCommentPrefix(pos);
            }
        });
    }

    /**
     * ?</br>
     * 
     * @param pos
     */
    private void setCommentContent(int pos, boolean clickBtn) {
        // ???
        if (clickBtn) {
            mReplyUser = null;
            mCommentEditText.setHint("");
            return;
        }
        String replyText = getCommentHint(pos, clickBtn);
        mCommentEditText.setHint(replyText);
    }

    /**
     * Comment itemitem????Editview?
     */

    @Override
    protected void performClickCommentItem(final WrapperListView commListView, final View itemView,
            final int position, boolean clickBtn) {
        mClickItemView = itemView;
        if (commListView != null) {
            // ?
            int lastVisible = commListView.getLastVisiblePosition();
            mScrollDis = 0;
            for (int i = position; i < lastVisible; i++) {
                mScrollDis += commListView.getChildAt(i).getHeight();
            }
        }

        // ??
        setCommentContent(position, clickBtn);
        // ?
        showInputMethod();
        showCommentLayout(position, clickBtn);
    }

    @Override
    protected void clickActionButton(FeedItemViewHolder viewHolder, int position) {
        mCurFeedItemIndex = position + 1;
        super.clickActionButton(viewHolder, position);
    }

    @Override
    protected void updateCommentListView(WrapperListView commentListView, FeedItem feedItem, Comment comment) {
        super.updateCommentListView(commentListView, feedItem, comment);
        mFeedLvAdapter.notifyDataSetChanged();
    }

    @Override
    protected void likeSuccess(String feedId, String likeId) {
        super.likeSuccess(feedId, likeId);
        mFeedsListView.requestLayout();
        // ?
        mFeedLvAdapter.notifyDataSetChanged();
    }

    private void resetCommentLayout() {
        if (mCommentLayout != null) {
            mCommentLayout.setVisibility(View.INVISIBLE);
        }
        if (mCommentEditText != null) {
            mCommentEditText.setText("");
        }
    }

    private void unregisterReceiver() {

        if (mPostBroadcastReceiver != null) {
            getActivity().unregisterReceiver(mPostBroadcastReceiver);
        }

        if (mUserBroadcastReceiver != null) {
            getActivity().unregisterReceiver(mUserBroadcastReceiver);
        }

        if (mBroadcastReceiver != null) {
            getActivity().unregisterReceiver(mBroadcastReceiver);
        }
    }

    @Override
    public void onDestroy() {
        unregisterReceiver();
        super.onDestroy();
    }

    /**
     * ??show or hide?</br>
     * 
     * @param type
     * @param view
     */
    private void sendInputMethodMessage(int type, View view) {
        Message message = mHandler.obtainMessage(type);
        message.obj = view;
        mHandler.sendMessage(message);
    }

    void cleanAdapterData() {
        mFeedLvAdapter.getDataSource().clear();
        mFeedLvAdapter.notifyDataSetChanged();
    }

}