com.tweetlanes.android.view.TweetFeedFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.tweetlanes.android.view.TweetFeedFragment.java

Source

/*
 * Copyright (C) 2013 Chris Lacy Licensed under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
 * or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */

package com.tweetlanes.android.view;

import android.app.Activity;
import android.content.*;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.view.*;
import android.view.View.OnClickListener;
import android.widget.*;
import android.widget.AbsListView.OnScrollListener;
import com.tweetlanes.android.AppSettings;
import com.tweetlanes.android.Constant;
import com.tweetlanes.android.Constant.SystemEvent;
import com.tweetlanes.android.Notifier;
import com.tweetlanes.android.R;
import com.tweetlanes.android.model.AccountDescriptor;
import com.tweetlanes.android.model.ComposeTweetDefault;
import com.tweetlanes.android.util.LazyImageLoader;
import com.tweetlanes.android.widget.pulltorefresh.PullToRefreshBase.OnLastItemVisibleListener;
import com.tweetlanes.android.widget.pulltorefresh.PullToRefreshBase.OnRefreshListener;
import com.tweetlanes.android.widget.pulltorefresh.PullToRefreshListView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.socialnetlib.android.SocialNetConstant;
import org.tweetalib.android.*;
import org.tweetalib.android.TwitterConstant.StatusesType;
import org.tweetalib.android.callback.TwitterFetchStatusesFinishedCallback;
import org.tweetalib.android.model.TwitterStatus;
import org.tweetalib.android.model.TwitterStatuses;
import org.tweetalib.android.model.TwitterUsers;

import java.util.ArrayList;

public final class TweetFeedFragment extends BaseLaneFragment {

    public static TweetFeedFragment newInstance(int laneIndex, final TwitterContentHandleBase handleBase,
            final String screenName, final String laneIdentifier, final String currentAccountKey) {

        TweetFeedFragment fragment = new TweetFeedFragment();

        fragment.mContentHandle = TwitterManager.get().getContentHandle(handleBase, screenName, laneIdentifier,
                currentAccountKey);

        fragment.configureBaseLaneFragment(laneIndex, fragment.mContentHandle.getTypeAsString(),
                new ConfigureBundleListener() {

                    @Override
                    public void addValues(Bundle args) {
                        // TODO: serializing is a slow way of doing this...
                        args.putSerializable(KEY_HANDLE_BASE, handleBase);
                        args.putString(KEY_SCREEN_NAME, screenName);
                        args.putString(KEY_LANE_IDENTIFIER, laneIdentifier);
                    }

                });

        return fragment;
    }

    private PullToRefreshListView mTweetFeedListView;
    private TweetFeedListAdapter mTweetFeedListAdapter;
    private TextView mListHeadingTextView;
    private ImageView mListHeadingHideImage;
    boolean mHidingListHeading = false;
    private TwitterContentHandle mContentHandle;
    private TwitterStatuses _mStatusFeed; // Don't touch me directly. Use the
    // accessors
    private TwitterStatuses _mCachedStatusFeed;
    private TwitterFetchStatusesFinishedCallback mTweetDataRefreshCallback;
    private TwitterFetchStatusesFinishedCallback mTweetDataLoadMoreCallback;
    private ViewSwitcher mViewSwitcher;
    private ArrayList<TweetFeedItemView> mSelectedItems = new ArrayList<TweetFeedItemView>();
    private ArrayList<Long> mConverstaionViewIds = new ArrayList<Long>();
    private MultipleTweetSelectionCallback mMultipleTweetSelectionCallback;

    private Long mNewestTweetId;
    private Long mOldestTweetId;
    private Long mRefreshingOldestTweetId;
    private boolean mMoreStatusesAvailable = true;
    private Long mResumeStatusId;

    private LazyImageLoader mProfileImageLoader;
    private LazyImageLoader mPreviewImageLoader;

    /*
     * (non-Javadoc)
     *
     * @see
     * android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater,
     * android.view.ViewGroup, android.os.Bundle)
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);

        mProfileImageLoader = getApp().getProfileImageLoader();
        mPreviewImageLoader = getApp().getPreviewImageLoader();

        mContentHandle = TwitterManager.get().getContentHandle(getContentHandleBase(), getScreenName(),
                getLaneIdentifier(), getApp().getCurrentAccountKey());

        View resultView = inflater.inflate(R.layout.lane, null);
        configureLaneWidth(resultView);

        mViewSwitcher = (ViewSwitcher) resultView.findViewById(R.id.profileSwitcher);
        mListHeadingTextView = (TextView) resultView.findViewById(R.id.list_heading);
        mListHeadingHideImage = (ImageView) resultView.findViewById(R.id.list_hide);
        mListHeadingHideImage.setOnClickListener(mListHeadingHideImageOnClickListener);
        mMultipleTweetSelectionCallback = new MultipleTweetSelectionCallback();
        mTweetFeedListAdapter = new TweetFeedListAdapter(inflater);

        mTweetFeedListView = (PullToRefreshListView) resultView.findViewById(R.id.pull_to_refresh_listview);
        mTweetFeedListView.getRefreshableView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
        mTweetFeedListView.getRefreshableView().setMultiChoiceModeListener(mMultipleTweetSelectionCallback);
        mTweetFeedListView.getRefreshableView().setOnScrollListener(mTweetFeedOnScrollListener);
        mTweetFeedListView.getRefreshableView().setAdapter(mTweetFeedListAdapter);
        mTweetFeedListView.setOnRefreshListener(mTweetFeedOnRefreshListener);
        mTweetFeedListView.setOnLastItemVisibleListener(mTweetFeedOnLastItemVisibleListener);

        configureInitialStatuses();

        mRefreshTimestampsHandler.removeCallbacks(mRefreshTimestampsTask);
        mRefreshTimestampsHandler.postDelayed(mRefreshTimestampsTask, REFRESH_TIMESTAMPS_INTERVAL);

        LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mVolumeUpKeyDownReceiver,
                new IntentFilter("" + SystemEvent.VOLUME_UP_KEY_DOWN));
        LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mVolumeDownKeyDownReceiver,
                new IntentFilter("" + SystemEvent.VOLUME_DOWN_KEY_DOWN));

        return resultView;
    }

    /*
     *
    */
    private void configureInitialStatuses() {
        boolean autoUpdateStatuses = false;

        boolean configuredCachedStatuses = configureCachedStatuses();

        TwitterStatuses cachedFeed = TwitterManager.get().getContentFeed(mContentHandle);
        if (cachedFeed != null && cachedFeed.getStatusCount(getBaseLaneActivity().mStatusesFilter) > 0) {
            setStatusFeed(cachedFeed, true);
        } else {
            if (configuredCachedStatuses) {
                autoUpdateStatuses = true;
            } else {
                setStatusFeed(null, true);
            }
        }

        if (getStatusFeed() == null || getFilteredStatusCount() == 0) {
            updateViewVisibility(false);
            setInitialDownloadState(InitialDownloadState.WAITING);
        } else {
            if (autoUpdateStatuses == true && mTweetDataRefreshCallback == null) {
                fetchNewestTweets();
            }

            setInitialDownloadState(InitialDownloadState.DOWNLOADED);
            updateViewVisibility(true);
        }
    }

    /*
    *
    */
    void fetchNewestTweets() {
        if (mNewestTweetId != null) {
            fetchNewestTweets(mNewestTweetId.longValue(), null);
        }
    }

    /*
    *
    */
    void fetchNewestTweets(final long sinceStatusId, Long maxStatusId) {
        if (mTweetDataRefreshCallback == null) {
            mTweetDataRefreshCallback = new TwitterFetchStatusesFinishedCallback() {

                @Override
                public void finished(TwitterFetchResult fetchResult, TwitterStatuses feed,
                        TwitterContentHandle contentHandle) {
                    if (!contentHandle.getCurrentAccountKey().equals(getApp().getCurrentAccountKey())) {
                        Log.e("Statuses", "account changed, don't display statuses");
                        return;
                    }

                    beginListHeadingCount();

                    onRefreshFinished(fetchResult, feed);
                    mTweetDataRefreshCallback = null;

                    if (fetchResult.isSuccessful()) {
                        // If there are more statuses to get, go get 'em
                        if (feed != null && feed.getNewStatusesMaxId() != null) {
                            fetchNewestTweets(sinceStatusId, feed.getNewStatusesMaxId());
                            // Log.d("Statuses", "Fetching more");
                        } else {
                            // Log.d("Statuses", "DONE!!!");
                        }
                    }
                }
            };

            Log.d("api-call", "--fetchNewestTweets(" + mContentHandle.getStatusesType().toString() + ")");
            TwitterPaging paging = new TwitterPaging(null, null, sinceStatusId, maxStatusId);
            TwitterManager.get().triggerFetchStatuses(mContentHandle, paging, mTweetDataRefreshCallback,
                    getAsyncTaskPriorityOffset());
            if (getBaseLaneActivity().isComposing() == false
                    && !(mSelectedItems == null || mSelectedItems.size() == 0)) {
                getBaseLaneActivity().finishCurrentActionMode();
            }
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see com.tweetlanes.android.view.BaseLaneFragment#onJumpToTop()
     */
    @Override
    public void onJumpToTop() {
        if (mTweetFeedListView != null) {
            ListView listView = mTweetFeedListView.getRefreshableView();
            if (listView != null && listView.getAdapter() != null && listView.getAdapter().isEmpty() == false) {
                listView.setSelection(0);
            }
        }
    }

    private static final String KEY_VISIBLE_STATUS_ID = "visibleStatusId";
    private static final String KEY_STATUSES = "statuses";

    /*
     * (non-Javadoc)
     *
     * @see com.tweetlanes.android.view.BaseLaneFragment#clearLocalCache()
     */
    @Override
    public void clearLocalCache() {
        _mStatusFeed = null;
        _mCachedStatusFeed = null;
    }

    /*
     * (non-Javadoc)
     *
     * @see com.tweetlanes.android.view.BaseLaneFragment#getContentToCache()
     */
    @Override
    public String getDataToCache() {

        TwitterStatuses feed = getStatusFeed();
        if (feed == null || feed.getStatusCount() == 0) {
            return null;
        }

        if (mTweetFeedListAdapter != null && mTweetFeedListView != null) {
            ListView listView = mTweetFeedListView.getRefreshableView();
            int visibleIndex = Math.max(listView.getFirstVisiblePosition() - 1, 0);

            // View view = (View)listView.getItemAtPosition(visible);

            int startIndex = Math.max(0, visibleIndex - 5);
            // int endIndex = Math.min(visibleIndex + 5,
            // Math.min(getStatusFeed().getStatusCount(),
            // mTweetFeedListAdapter.getCount()));
            int endIndex = Math.min(visibleIndex + 5, feed.getStatusCount());

            Long visibleStatusId = null;

            TwitterStatuses statuses = new TwitterStatuses();
            for (int i = startIndex; i < endIndex; i++) {
                TwitterStatus status = feed.getStatus(i);
                if (status == null) {
                    break;
                }

                if (i == visibleIndex) {
                    visibleStatusId = status.mId;
                    // Log.d("StatusCache", "Set visible: " +
                    // status.getStatus());
                }

                statuses.add(status);
            }

            if (statuses.getStatusCount() > 0 && visibleStatusId != null) {
                JSONObject object = new JSONObject();
                try {
                    object.put(KEY_VISIBLE_STATUS_ID, visibleStatusId);
                    JSONArray statusArray = new JSONArray();
                    int statusCount = statuses.getStatusCount();
                    for (int i = 0; i < statusCount; ++i) {
                        TwitterStatus status = statuses.getStatus(i);
                        statusArray.put(status.toString());
                    }
                    object.put(KEY_STATUSES, statusArray);

                } catch (JSONException e) {
                    e.printStackTrace();
                }
                return object.toString();
            }
        }

        return null;
    }

    /*
    *
    */
    boolean configureCachedStatuses() {

        String cachedData = getCachedData();
        if (cachedData != null) {
            JSONObject object;
            try {
                object = new JSONObject(cachedData);
                if (object.has(KEY_VISIBLE_STATUS_ID)) {
                    mResumeStatusId = object.getLong(KEY_VISIBLE_STATUS_ID);
                    if (object.has(KEY_STATUSES)) {
                        String statusesAsString = object.getString(KEY_STATUSES);
                        if (statusesAsString != null) {
                            _mCachedStatusFeed = new TwitterStatuses();
                            JSONArray jsonArray = new JSONArray(statusesAsString);
                            for (int i = 0; i < jsonArray.length(); i++) {
                                String statusString = jsonArray.getString(i);
                                TwitterStatus status = new TwitterStatus(statusString);
                                _mCachedStatusFeed.add(status);
                            }

                            setStatusFeed(_mCachedStatusFeed, false);
                            return true;
                        }
                    }
                }
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        return false;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * com.tweetlanes.android.view.BaseLaneFragment#triggerInitialDownload()
     */
    public void triggerInitialDownload() {
        mTweetDataRefreshCallback = new TwitterFetchStatusesFinishedCallback() {

            @Override
            public void finished(TwitterFetchResult fetchResult, TwitterStatuses feed,
                    TwitterContentHandle handle) {
                if (!handle.getCurrentAccountKey().equals(getApp().getCurrentAccountKey())) {
                    Log.e("Statuses", "account changed, don't display statuses");
                    return;
                }

                if (feed != null) {
                    setStatusFeed(feed, true);
                }
                updateViewVisibility(true);
                setInitialDownloadState(InitialDownloadState.DOWNLOADED);
                mTweetDataRefreshCallback = null;
            }
        };

        Log.d("api-call", "--triggerInitialDownload((" + mContentHandle.getStatusesType().toString() + ")");
        TwitterManager.get().triggerFetchStatuses(mContentHandle, null, mTweetDataRefreshCallback,
                getAsyncTaskPriorityOffset());
        setInitialDownloadState(InitialDownloadState.DOWNLOADING);
    }

    /*
    *
    */
    private BroadcastReceiver mVolumeUpKeyDownReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {

            if (AppSettings.get().isVolScrollEnabled() == true) {
                ListView listView = mTweetFeedListView.getRefreshableView();
                int firstPos = listView.getFirstVisiblePosition();
                int nextPos = firstPos - 1;
                // Greater than 0 so we ignore the pullToRefresh
                if (nextPos > 0) {
                    listView.setSelection(nextPos);
                    // listView.smoothScrollToPosition(nextPos);
                    listView.setScrollbarFadingEnabled(false);
                }
            }
        }
    };

    /*
    *
    */
    private BroadcastReceiver mVolumeDownKeyDownReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {

            if (AppSettings.get().isVolScrollEnabled() == true) {
                ListView listView = mTweetFeedListView.getRefreshableView();

                int nextPos = Math.max(1, listView.getFirstVisiblePosition()) + 1;
                int last = listView.getLastVisiblePosition();
                if (nextPos < last) {
                    listView.setSelection(nextPos);
                    // listView.smoothScrollToPosition(nextPos);
                    listView.setScrollbarFadingEnabled(false);
                }
            }
        }
    };

    /*
    *
    */
    enum ScrollDirection {
        UNKNOWN, TO_NEWER, TO_OLDER,
    }

    /*
    *
    */
    private class ScrollTracker {

        private ScrollDirection mLastScrollDirection = ScrollDirection.UNKNOWN;
        private int mFirstVisibleYOffset = 0;
        private int mOldFirstVisibleYOffset = 0;
        private int mOldFirstVisibleItem = 0;
        private int mOldTotalItemCount = 0;

        ScrollTracker() {
            mLastScrollDirection = ScrollDirection.UNKNOWN;
            mFirstVisibleYOffset = 0;
            mOldFirstVisibleYOffset = 0;
            mOldFirstVisibleItem = 0;
            mOldTotalItemCount = 0;
        }

        void update(int firstVisibleItem, int totalItemCount, Integer yOffset) {

            if (yOffset != null) {
                mOldFirstVisibleYOffset = mFirstVisibleYOffset;
                mFirstVisibleYOffset = yOffset;
            }

            if (mOldTotalItemCount != totalItemCount) {
                // mLastScrollDirection = ScrollDirection.UNKNOWN;
            } else {
                if (mOldFirstVisibleItem == firstVisibleItem) {
                    if (mOldFirstVisibleYOffset > mFirstVisibleYOffset) {
                        mLastScrollDirection = ScrollDirection.TO_OLDER;
                    } else if (mOldFirstVisibleYOffset < mFirstVisibleYOffset) {
                        mLastScrollDirection = ScrollDirection.TO_NEWER;
                    }
                } else {
                    if (mOldFirstVisibleItem > firstVisibleItem) {
                        mLastScrollDirection = ScrollDirection.TO_NEWER;
                    } else if (mOldFirstVisibleItem < firstVisibleItem) {
                        mLastScrollDirection = ScrollDirection.TO_OLDER;
                    }
                }
            }

            mOldTotalItemCount = totalItemCount;
            mOldFirstVisibleItem = firstVisibleItem;

            // Log.d("Statuses", "Direction: " +
            // mLastScrollDirection.toString());
        }

        ScrollDirection getLastScrollDirection() {
            return mLastScrollDirection;
        }

        int getFirstVisibleYOffset() {
            return mFirstVisibleYOffset;
        }
    }

    private ScrollTracker mScrollTracker = new ScrollTracker();

    /*
    *
    */
    private OnScrollListener mTweetFeedOnScrollListener = new OnScrollListener() {

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

            Integer yOffset = null;
            if (view != null && view.getChildAt(0) != null) {
                yOffset = view.getChildAt(0).getTop();
            }
            mScrollTracker.update(firstVisibleItem, totalItemCount, yOffset);

            updateListHeading(firstVisibleItem);

            getVisibleStatus();
        }

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {

            if (scrollState == 0) {
                // Restore scrollbar fading, which may have been set to false
                // when scrolling through items via the volume keys
                view.setScrollbarFadingEnabled(true);
            }

            mTweetFeedListView.onScrollStateChanged(view, scrollState);
        }

    };

    /*
    *
    */
    private OnLastItemVisibleListener mTweetFeedOnLastItemVisibleListener = new OnLastItemVisibleListener() {

        @Override
        public void onLastItemVisible() {
            if (mOldestTweetId != null) {
                if (mRefreshingOldestTweetId == null) {
                    if (mTweetDataLoadMoreCallback == null) {
                        mTweetDataLoadMoreCallback = new TwitterFetchStatusesFinishedCallback() {

                            @Override
                            public void finished(TwitterFetchResult result, TwitterStatuses feed,
                                    TwitterContentHandle handle) {
                                if (!handle.getCurrentAccountKey().equals(getApp().getCurrentAccountKey())) {
                                    Log.e("Statuses", "account changed, don't display statuses");
                                    return;
                                }

                                if (feed != null) {
                                    setStatusFeed(feed, true);
                                }

                                if (mRefreshingOldestTweetId != null && mOldestTweetId != null
                                        && mRefreshingOldestTweetId.longValue() == mOldestTweetId.longValue()) {
                                    mMoreStatusesAvailable = false;
                                }
                                mRefreshingOldestTweetId = null;
                                mTweetDataLoadMoreCallback = null;

                                if (mTweetFeedListAdapter != null) {
                                    mTweetFeedListAdapter.notifyDataSetChanged();
                                }
                            }
                        };

                        Log.d("api-call", "--OnLastItemVisibleListener(("
                                + mContentHandle.getStatusesType().toString() + ")");
                        TwitterManager.get().triggerFetchStatuses(mContentHandle,
                                TwitterPaging.createGetOlder(mOldestTweetId), mTweetDataLoadMoreCallback,
                                getAsyncTaskPriorityOffset());
                        mRefreshingOldestTweetId = mOldestTweetId;
                    }
                }
            }
        }
    };

    Long mTwitterStatusIdWhenRefreshed;
    int mCurrentFirstVisibleItem = 0;

    /*
    *
    */
    void beginListHeadingCount() {
        if (mTwitterStatusIdWhenRefreshed == null) {
            if (getStatusFeed() != null && mCurrentFirstVisibleItem < getStatusFeed().getStatusCount()) {
                TwitterStatus status = getStatusFeed().getStatus(mCurrentFirstVisibleItem);
                mTwitterStatusIdWhenRefreshed = status.mId;
                mHidingListHeading = false;
            }
        }
    }

    /*
    *
    */ OnClickListener mListHeadingHideImageOnClickListener = new OnClickListener() {

        @Override
        public void onClick(View v) {
            mHidingListHeading = true;
            setListHeadingVisiblilty(View.GONE);
        }
    };

    /*
    *
    */
    void setListHeadingVisiblilty(int value) {
        mListHeadingTextView.setVisibility(value);
        mListHeadingHideImage.setVisibility(value);
    }

    /*
    *
    */
    void updateListHeading(int firstVisibleItem) {

        SocialNetConstant.Type socialNetType = getApp().getCurrentAccount().getSocialNetType();

        // Add 1 so that we don't display the 'x new tweets' on the first tweet
        if (mTwitterStatusIdWhenRefreshed != null && firstVisibleItem > 1) {
            if (mScrollTracker.getLastScrollDirection() == ScrollDirection.TO_OLDER) {
                setListHeadingVisiblilty(View.GONE);
            } else {
                if (mHidingListHeading == false) {
                    setListHeadingVisiblilty(View.VISIBLE);
                    mListHeadingTextView.setText((firstVisibleItem - 1) + " "
                            + getString(firstVisibleItem == 2
                                    ? socialNetType == SocialNetConstant.Type.Twitter ? R.string.new_tweet
                                            : R.string.new_post
                                    : socialNetType == SocialNetConstant.Type.Twitter ? R.string.new_tweets
                                            : R.string.new_posts));
                }
            }
        } else {
            setListHeadingVisiblilty(View.GONE);
            mTwitterStatusIdWhenRefreshed = null;
        }

        mCurrentFirstVisibleItem = firstVisibleItem;
    }

    /*
    *
    */
    private TwitterStatus getVisibleStatus() {

        TwitterStatus visibleStatus = null;

        if (getStatusFeed() != null && mTweetFeedListView != null
                && mTweetFeedListView.getRefreshableView() != null) {
            int visiblePosition = mTweetFeedListView.getRefreshableView().getFirstVisiblePosition();

            if (visiblePosition < getStatusFeed().getStatusCount()) {
                visibleStatus = getStatusFeed().getStatus(visiblePosition);
                if (visibleStatus != null) {
                    if (getLaneIndex() == getApp().getCurrentAccount()
                            .getCurrentLaneIndex(Constant.LaneType.USER_MENTIONS)) {
                        SharedPreferences preferences = PreferenceManager
                                .getDefaultSharedPreferences(getBaseLaneActivity());
                        long lastDisplayedMentionId = preferences
                                .getLong(Notifier.SHARED_PREFERENCES_KEY_NOTIFICATION_LAST_DISPLAYED_MENTION_ID
                                        + getApp().getCurrentAccountKey(), 0);

                        if (visibleStatus.mId >= lastDisplayedMentionId) {
                            Notifier.saveLastNotificationActioned(getBaseLaneActivity(),
                                    getApp().getCurrentAccountKey(), visibleStatus.mId);
                            Notifier.cancel(getBaseLaneActivity(), getApp().getCurrentAccountKey());
                        }
                    }
                }
            }
        }

        return visibleStatus;
    }

    /*
    *
    */
    private void onRefreshFinished(TwitterFetchResult result, TwitterStatuses feed) {

        if (mTweetFeedListView == null || mTweetFeedListView.getRefreshableView() == null) {
            return;
        }

        TwitterStatus visibleStatus = getVisibleStatus();

        int oldFeedCount = getFilteredStatusCount();

        if (feed != null) {
            setStatusFeed(feed, true);
        }

        int newFeedCount = getFilteredStatusCount();
        mTweetFeedListView.onRefreshComplete();
        mTweetFeedListAdapter.notifyDataSetChanged();

        int newCount = newFeedCount - oldFeedCount;
        if (newCount > 0) {
            if (visibleStatus != null) {
                Integer statusIndex = getStatusFeed().getStatusIndex(visibleStatus.mId);
                if (statusIndex != null) {
                    mTweetFeedListView.getRefreshableView().setSelectionFromTop(statusIndex.intValue(),
                            mScrollTracker.getFirstVisibleYOffset());
                }
            }
        }
        mTweetDataRefreshCallback = null;
    }

    /*
    *
    */
    private OnRefreshListener mTweetFeedOnRefreshListener = new OnRefreshListener() {

        @Override
        public void onRefresh() {
            fetchNewestTweets();
        }
    };

    /*
     * (non-Javadoc)
     *
     * @see
     * android.support.v4.app.Fragment#onOptionsItemSelected(android.view.MenuItem
     * )
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_replies_visibility:
            getBaseLaneActivity().mStatusesFilter
                    .setShowReplies(!getBaseLaneActivity().mStatusesFilter.getShowReplies());
            item.setTitle(
                    getString(getBaseLaneActivity().mStatusesFilter.getShowReplies() ? R.string.action_hide_replies
                            : R.string.action_show_replies));
            mTweetFeedListAdapter.notifyDataSetChanged();
            return false;

        case R.id.action_retweets_visibility:
            getBaseLaneActivity().mStatusesFilter
                    .setShowRetweets(!getBaseLaneActivity().mStatusesFilter.getShowRetweets());
            item.setTitle(getString(
                    getBaseLaneActivity().mStatusesFilter.getShowRetweets() ? R.string.action_hide_retweets
                            : R.string.action_show_retweets));
            mTweetFeedListAdapter.notifyDataSetChanged();
            return false;
        }

        return false;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * com.tweetlanes.android.view.BaseLaneFragment#configureOptionsMenu(android
     * .view.Menu)
     */
    @Override
    public boolean configureOptionsMenu(MenuInflater inflater, Menu menu) {

        if (inflater != null && mContentHandle != null
                && (mContentHandle.getStatusesType() == StatusesType.USER_TIMELINE
                        || mContentHandle.getStatusesType() == StatusesType.USER_HOME_TIMELINE
                        || mContentHandle.getStatusesType() == StatusesType.USER_LIST_TIMELINE)) {

            if (getBaseLaneActivity() instanceof HomeActivity) {
                inflater.inflate(R.menu.home_tweet_feed_action_bar, menu);
            } else {
                inflater.inflate(R.menu.tweet_feed_action_bar, menu);
            }

            for (int i = 0; i < menu.size(); i++) {
                MenuItem menuItem = menu.getItem(i);
                if (menuItem.getItemId() == R.id.action_feed_filter) {
                    SubMenu subMenu = menuItem.getSubMenu();
                    if (subMenu != null) {
                        SocialNetConstant.Type socialNetType = getApp().getCurrentAccount().getSocialNetType();
                        int subMenuSize = subMenu.size();
                        for (int j = 0; j < subMenuSize; j++) {
                            MenuItem subMenuItem = subMenu.getItem(j);
                            switch (subMenuItem.getItemId()) {
                            case R.id.action_replies_visibility:

                                subMenuItem
                                        .setTitle(getString(getBaseLaneActivity().mStatusesFilter.getShowReplies()
                                                ? R.string.action_hide_replies
                                                : R.string.action_show_replies));
                                break;

                            case R.id.action_retweets_visibility:
                                subMenuItem
                                        .setTitle(getString(getBaseLaneActivity().mStatusesFilter.getShowRetweets()
                                                ? socialNetType == SocialNetConstant.Type.Twitter
                                                        ? R.string.action_hide_retweets
                                                        : R.string.action_hide_retweets_adn
                                                : socialNetType == SocialNetConstant.Type.Twitter
                                                        ? R.string.action_show_retweets
                                                        : R.string.action_show_retweets_adn));
                                break;

                            default:
                                break;
                            }

                        }
                    }
                }
            }

            return true;
        }

        return false;
    }

    /*
     * (non-Javadoc)
     *
     * @see android.support.v4.app.Fragment#onDestroy()
     */
    @Override
    public void onDestroy() {

        LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mVolumeUpKeyDownReceiver);
        LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mVolumeDownKeyDownReceiver);

        super.onDestroy();
    }

    /*
    *
    */
    private void updateViewVisibility(boolean loadHasFinished) {

        mViewSwitcher.reset();

        if (loadHasFinished == false && (getStatusFeed() == null || getFilteredStatusCount() == 0)) {
            mViewSwitcher.setDisplayedChild(0);
        } else {
            mViewSwitcher.setDisplayedChild(1);
            mTweetFeedListAdapter.notifyDataSetChanged();
            if (mResumeStatusId != null && getStatusFeed() != null) {
                Integer statusIndex = getStatusFeed().getStatusIndex(mResumeStatusId);
                if (statusIndex != null) {
                    mTweetFeedListView.getRefreshableView().setSelectionFromTop(statusIndex.intValue() + 1, 0);
                }
            }
        }
    }

    private static final String KEY_HANDLE_BASE = "handleBase";
    private static final String KEY_SCREEN_NAME = "screenName";
    private static final String KEY_LANE_IDENTIFIER = "laneIdentifier";

    private TwitterContentHandleBase getContentHandleBase() {
        return (TwitterContentHandleBase) getArguments().getSerializable(KEY_HANDLE_BASE);
    }

    private String getScreenName() {
        return getArguments().getString(KEY_SCREEN_NAME);
    }

    private String getLaneIdentifier() {
        return getArguments().getString(KEY_LANE_IDENTIFIER);
    }

    private void setStatusFeed(TwitterStatuses statuses, boolean addCachedStatuses) {

        mNewestTweetId = null;
        mOldestTweetId = null;

        if (statuses == null) {
            _mStatusFeed = null;
        } else {
            _mStatusFeed = new TwitterStatuses(statuses);
        }

        if (addCachedStatuses && _mCachedStatusFeed != null && _mCachedStatusFeed.getStatusCount() > 0) {
            _mStatusFeed.insert(_mCachedStatusFeed);
        }

        if (_mStatusFeed != null && _mStatusFeed.getStatusCount() > 0) {
            mNewestTweetId = _mStatusFeed.getStatus(0).mId;
            mOldestTweetId = _mStatusFeed.getStatus(_mStatusFeed.getStatusCount() - 1).mId;
        }
    }

    private TwitterStatuses getStatusFeed() {
        return _mStatusFeed;
    }

    private int getFilteredStatusCount() {
        return getStatusFeed() != null ? getStatusFeed().getStatusCount(getBaseLaneActivity().mStatusesFilter) : 0;
    }

    private final int REFRESH_TIMESTAMPS_INTERVAL = 1000 * 30;
    private Handler mRefreshTimestampsHandler = new Handler();
    private final Runnable mRefreshTimestampsTask = new Runnable() {

        public void run() {

            if (getFilteredStatusCount() > 0) {
                mTweetFeedListAdapter.notifyDataSetChanged();
            }

            mRefreshTimestampsHandler.postDelayed(this, REFRESH_TIMESTAMPS_INTERVAL);
        }
    };

    /*
    *
    */
    private boolean onTweetFeedItemSingleTap(View view, int position) {

        if (mSelectedItems.size() == 0) {
            TweetFeedItemView tweetFeedItemView = (TweetFeedItemView) (view);
            TwitterStatus status = tweetFeedItemView.getTwitterStatus();
            Intent tweetSpotlightIntent = new Intent(getActivity(), TweetSpotlightActivity.class);
            tweetSpotlightIntent.putExtra("statusId", Long.toString(status.mId));
            getActivity().startActivity(tweetSpotlightIntent);
            return true;
        } else {
            onTweetFeedItemLongPress(view, position);
            return true;
        }

    }

    /*
    *
    */
    private void onTweetFeedItemLongPress(View view, int position) {

        boolean isChecked = mTweetFeedListView.getRefreshableView().getCheckedItemPositions().get(position) == true
                ? true
                : false;
        mTweetFeedListView.getRefreshableView().setItemChecked(position, !isChecked);

        TweetFeedItemView tweetFeedItemView = (TweetFeedItemView) (view);

        for (int index = 0; index < mSelectedItems.size(); index++) {
            TweetFeedItemView item = mSelectedItems.get(index);
            if (item.getTwitterStatus() != null && tweetFeedItemView.getTwitterStatus() != null) {
                if (item.getTwitterStatus().mId == tweetFeedItemView.getTwitterStatus().mId) {
                    mSelectedItems.remove(index);
                    break;
                }
            }
        }

        if (!isChecked) {
            mSelectedItems.add(tweetFeedItemView);
        }

        if (mSelectedItems.size() > 0 && getApp() != null) {
            mMultipleTweetSelectionCallback
                    .setIsFavorited(getSelectedFavoriteState() == ItemSelectedState.ALL ? true : false);
            getBaseLaneActivity().setComposeTweetDefault(
                    new ComposeTweetDefault(getApp().getCurrentAccountScreenName(), getSelectedStatuses()));
        } else {
            mMultipleTweetSelectionCallback.setIsFavorited(false);
            getBaseLaneActivity().setComposeTweetDefault();
        }
    }

    /*
    *
    */
    private TwitterStatuses getSelectedStatuses() {

        TwitterStatuses selectedList = new TwitterStatuses();

        for (int i = 0; i < mSelectedItems.size(); i++) {
            TweetFeedItemView tweetFeedItemView = mSelectedItems.get(i);
            TwitterStatus status = tweetFeedItemView.getTwitterStatus();
            if (status != null) {
                selectedList.add(status);
            }
        }

        return selectedList.getStatusCount() > 0 ? selectedList : null;
    }

    /*
    *
    */
    private TwitterStatus getFirstSelectedStatus() {

        for (int i = 0; i < mSelectedItems.size(); i++) {
            TweetFeedItemView tweetFeedItemView = mSelectedItems.get(i);
            TwitterStatus status = tweetFeedItemView.getTwitterStatus();
            if (status != null) {
                return status;
            }
        }

        return null;
    }

    /*
    *
    */
    enum ItemSelectedState {
        NONE, SOME, ALL
    }

    /*
    *
    */
    private ItemSelectedState getSelectedFavoriteState() {

        int favoriteCount = 0;
        int selectedCount = mSelectedItems.size();
        for (int i = 0; i < selectedCount; i++) {
            TwitterStatus status = mSelectedItems.get(i).getTwitterStatus();
            if (status != null) {
                if (status.mIsFavorited) {
                    favoriteCount++;
                }
            }
        }

        if (favoriteCount == selectedCount) {
            return ItemSelectedState.ALL;
        } else if (favoriteCount != 0) {
            return ItemSelectedState.SOME;
        }
        return ItemSelectedState.NONE;
    }

    /*
    *
    */
    private class MultipleTweetSelectionCallback implements ListView.MultiChoiceModeListener {

        private MenuItem mFavoriteMenuItem;

        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            configure(mode);
            return true;
        }

        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return true;
        }

        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {

            final int itemId = item.getItemId();
            switch (itemId) {
            /*
             * case R.id.action_reply: getBaseLaneActivity().beginCompose();
             * break;
             */

            case R.id.action_share:
                getBaseLaneActivity().shareSelected(getFirstSelectedStatus());
                mode.finish();
                break;

            case R.id.action_retweet:
                getBaseLaneActivity().retweetSelected(getFirstSelectedStatus());
                mode.finish();
                break;

            case R.id.action_favorite: {
                TwitterModifyStatuses.FinishedCallback callback = TwitterManager.get()
                        .getSetStatusesInstance().new FinishedCallback() {

                            @Override
                            public void finished(boolean successful, TwitterStatuses statuses, Integer value) {
                                if (successful == true && value != null) {
                                    setIsFavorited(value == 1 ? true : false);

                                    TwitterStatuses cachedStatuses = getStatusFeed();

                                    if (statuses != null && statuses.getStatusCount() > 0) {
                                        for (int i = 0; i < statuses.getStatusCount(); i++) {
                                            TwitterStatus updatedStatus = statuses.getStatus(i);
                                            TwitterStatus cachedStatus = cachedStatuses
                                                    .findByStatusId(updatedStatus.mId);
                                            cachedStatus.setFavorite(updatedStatus.mIsFavorited);
                                        }
                                    }

                                    showToast(getString(value == 1 ? R.string.favorited_successfully
                                            : R.string.unfavorited_successfully));
                                }
                            }

                        };

                boolean newState = getSelectedFavoriteState() == ItemSelectedState.ALL ? false : true;
                TwitterManager.get().setFavorite(getSelectedStatuses(), newState, callback);
                mode.finish();
                break;
            }

            case R.id.action_manage_friendship:
                showToast(getString(R.string.functionality_not_implemented));
                mode.finish();
                break;

            case R.id.action_delete_status: {
                TwitterModifyStatuses.FinishedCallback callback = TwitterManager.get()
                        .getSetStatusesInstance().new FinishedCallback() {

                            final TwitterStatuses selected = getSelectedStatuses();

                            @Override
                            public void finished(boolean successful, TwitterStatuses statuses, Integer value) {
                                if (successful == true) {
                                    TwitterStatuses cachedStatuses = getStatusFeed();

                                    if (selected != null) {
                                        cachedStatuses.remove(selected);
                                    }

                                    showToast(getString(R.string.deleted_successfully));
                                }
                            }

                        };
                TwitterManager.get().deleteTweet(getSelectedStatuses(), callback);
                mode.finish();
                break;
            }

            case R.id.action_report_for_spam:
            case R.id.action_block: {
                AccountDescriptor account = getApp().getCurrentAccount();
                if (account != null) {

                    final TwitterStatuses selected = getSelectedStatuses();
                    if (selected != null && selected.getStatusCount() > 0) {

                        ArrayList<Long> userIds = new ArrayList<Long>();
                        for (int i = 0; i < selected.getStatusCount(); i++) {
                            userIds.add(selected.getStatus(i).mUserId);
                        }

                        TwitterFetchUsers.FinishedCallback callback = TwitterManager.get()
                                .getFetchUsersInstance().new FinishedCallback() {

                                    @Override
                                    public void finished(TwitterFetchResult result, TwitterUsers users) {

                                        getBaseLaneActivity().finishCurrentActionMode();

                                        if (getStatusFeed() != null) {
                                            getStatusFeed().remove(selected);
                                        }

                                        setStatusFeed(getStatusFeed(), true);
                                        mTweetFeedListAdapter.notifyDataSetChanged();
                                        mTweetFeedListView.onRefreshComplete();
                                        updateViewVisibility(true);

                                        if (result.isSuccessful() && users != null && users.getUserCount() > 0) {
                                            int userCount = users.getUserCount();
                                            String notice = null;
                                            if (itemId == R.id.action_report_for_spam) {
                                                if (userCount == 1) {
                                                    notice = "Reported @" + users.getUser(0).getScreenName()
                                                            + " for Spam.";
                                                } else {
                                                    notice = "Reported " + userCount + " users for Spam.";
                                                }
                                            } else {
                                                if (userCount == 1) {
                                                    notice = "Blocked @" + users.getUser(0).getScreenName() + ".";
                                                } else {
                                                    notice = "Blocked " + userCount + " users.";
                                                }
                                            }
                                            if (notice != null) {
                                                showToast(notice);
                                            }
                                        }
                                    }
                                };

                        if (item.getItemId() == R.id.action_report_for_spam) {
                            TwitterManager.get().reportSpam(account.getId(), userIds, callback);
                        } else {
                            TwitterManager.get().createBlock(account.getId(), userIds, callback);
                        }
                    }
                }
                break;
            }

            default:
                break;
            }
            return true;
        }

        public void onDestroyActionMode(ActionMode mode) {

            mSelectedItems.clear();

            // Don't update the default status when TweetCompose has focus
            if (getBaseLaneActivity().composeHasFocus() == false) {
                getBaseLaneActivity().setComposeDefault();
            }
        }

        public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
            configure(mode);
        }

        void configure(ActionMode mode) {

            BaseLaneActivity baseLaneActivity = (BaseLaneActivity) getActivity();
            if (baseLaneActivity == null || baseLaneActivity.isComposing() || mTweetFeedListView == null
                    || mTweetFeedListView.getRefreshableView() == null || mode == null) {
                return;
            }

            final int checkedCount = mTweetFeedListView.getRefreshableView().getCheckedItemCount();
            switch (checkedCount) {
            case 0:
                mode.setSubtitle(null);
                break;
            case 1: {
                mode.getMenu().clear();
                MenuInflater inflater = getActivity().getMenuInflater();
                inflater.inflate(R.menu.single_tweet_selected, mode.getMenu());
                storeMenuItems(mode.getMenu());
                mode.setTitle("");
                mode.setSubtitle("");
                break;
            }
            case 2: {
                mode.getMenu().clear();
                MenuInflater inflater = getActivity().getMenuInflater();
                inflater.inflate(R.menu.multiple_tweets_selected, mode.getMenu());
                storeMenuItems(mode.getMenu());
                mode.setTitle("Select Tweets");
                mode.setSubtitle("" + checkedCount + " items selected");
                break;
            }
            default: {
                mode.setTitle("Select Tweets");
                mode.setSubtitle("" + checkedCount + " items selected");
                break;
            }
            }
        }

        /*
         *
         */
        void storeMenuItems(Menu menu) {
            for (int i = 0; i < menu.size(); i++) {
                MenuItem menuItem = menu.getItem(i);
                if (menuItem.getItemId() == R.id.action_favorite) {
                    mFavoriteMenuItem = menuItem;
                    break;
                }
            }
        }

        /*
         *
         */
        void setIsFavorited(boolean favorited) {
            if (mFavoriteMenuItem != null) {
                boolean isDarkTheme = AppSettings.get().getCurrentTheme() == AppSettings.Theme.Holo_Dark;
                if (favorited) {
                    mFavoriteMenuItem.setIcon(
                            isDarkTheme ? R.drawable.ic_action_star_on_dark : R.drawable.ic_action_star_on_light);
                    mFavoriteMenuItem.setTitle(R.string.action_unfavorite);
                } else {
                    mFavoriteMenuItem.setIcon(
                            isDarkTheme ? R.drawable.ic_action_star_off_dark : R.drawable.ic_action_star_off_light);
                    mFavoriteMenuItem.setTitle(R.string.action_favorite);
                }
            }
        }
    }

    /*
     *
     */
    public boolean showConversationView(TwitterStatus status) {

        for (Long id : mConverstaionViewIds) {
            if (id == status.mId) {
                return true;
            }
        }

        return false;
    }

    /*
     *
     */
    private class TweetFeedListAdapter extends BaseAdapter {

        public TweetFeedListAdapter(LayoutInflater inflater) {
            mInflater = inflater;
        }

        /**
         * The number of items in the list is determined by the number of
         * speeches in our array.
         *
         * @see android.widget.ListAdapter#getCount()
         */
        public int getCount() {
            int count;
            if (getStatusFeed() != null) {
                count = getFilteredStatusCount() + 1; // +1 for the trailing
                // LoadMore view
            } else {
                count = 1;
            }

            return count;
        }

        /**
         * Since the data comes from an array, just returning the index is
         * sufficent to get at the data. If we were using a more complex data
         * structure, we would return whatever object represents one row in the
         * list.
         *
         * @see android.widget.ListAdapter#getItem(int)
         */
        public Object getItem(int position) {
            return position;
        }

        /**
         * Use the array index as a unique id.
         *
         * @see android.widget.ListAdapter#getItemId(int)
         */
        public long getItemId(int position) {
            return position;
        }

        /**
         * Make a TweetFeedItemView to hold each row.
         */
        public View getView(int position, View convertView, ViewGroup parent) {

            int statusCount = getFilteredStatusCount();

            View resultView = null;
            if (statusCount == 0 && position == getCount() - 1) {
                resultView = getLoadMoreView(convertView);
            } else if (position == statusCount) {
                resultView = getLoadMoreView(convertView);
            } else {
                resultView = getTweetFeedView(position, convertView);
            }

            return resultView;
        }

        /*
         *
         */
        View getTweetFeedView(int position, View convertView) {

            convertView = mInflater.inflate(R.layout.tweet_feed_item_received, null);

            TwitterStatus item = getStatusFeed().getStatus(position, getBaseLaneActivity().mStatusesFilter);

            TweetFeedItemView tweetFeedItemView = (TweetFeedItemView) convertView.findViewById(R.id.tweetFeedItem);

            TweetFeedItemView.Callbacks callbacks = new TweetFeedItemView.Callbacks() {

                @Override
                public boolean onSingleTapConfirmed(View view, int position) {
                    return onTweetFeedItemSingleTap(view, position);
                }

                @Override
                public void onLongPress(View view, int position) {
                    onTweetFeedItemLongPress(view, position);
                }

                @Override
                public Activity getActivity() {
                    return TweetFeedFragment.this.getActivity();
                }

                @Override
                public void onUrlClicked(TwitterStatus status) {
                    TwitterStatuses selected = getSelectedStatuses();
                    if (selected != null && selected.getStatusCount() == 1) {
                        if (selected.getStatus(0).mId == status.mId) {

                            // HACK ALERT: Finishing the actionMode in this
                            // callback will cause the link to be unable to be
                            // clicked.
                            // Adding a slight delay makes things work just fine
                            Runnable finishActionModeTask = new Runnable() {

                                public void run() {
                                    getBaseLaneActivity().finishCurrentActionMode();
                                }
                            };
                            mHandler.postDelayed(finishActionModeTask, 90);
                        }
                    }

                }

                @Override
                public void onConversationViewToggle(long statusId, boolean show) {
                    if (show) {
                        boolean add = true;
                        for (int i = 0; i < mConverstaionViewIds.size(); ++i) {
                            if (mConverstaionViewIds.get(i) == statusId) {
                                add = false;
                                break;
                            }
                        }
                        if (add) {
                            mConverstaionViewIds.add(statusId);
                        }
                    } else {
                        for (int i = 0; i < mConverstaionViewIds.size(); ++i) {
                            if (mConverstaionViewIds.get(i) == statusId) {
                                mConverstaionViewIds.remove(i);
                                break;
                            }
                        }
                    }
                }

                @Override
                public LayoutInflater getLayoutInflater() {
                    return mInflater;
                }

                @Override
                public LazyImageLoader getProfileImageLoader() {
                    return mProfileImageLoader;
                }

                @Override
                public LazyImageLoader getPreviewImageLoader() {
                    return mPreviewImageLoader;
                }

            };

            boolean showRetweetCount = mContentHandle
                    .getStatusesType() == TwitterConstant.StatusesType.RETWEETS_OF_ME;

            tweetFeedItemView.configure(item, position + 1, callbacks, true, showRetweetCount,
                    showConversationView(item), false, true, getApp().getCurrentAccount().getSocialNetType(),
                    getApp().getCurrentAccountKey());
            return tweetFeedItemView;
        }

        /*
         *
         */
        View getLoadMoreView(View convertView) {

            convertView = mInflater.inflate(R.layout.load_more, null);
            LoadMoreView loadMoreView = (LoadMoreView) convertView.findViewById(R.id.loadMoreView);

            LoadMoreView.Mode mode;
            if (getStatusFeed() == null || getFilteredStatusCount() == 0) {
                mode = LoadMoreView.Mode.NONE_FOUND;
            } else {
                mode = mMoreStatusesAvailable == true ? LoadMoreView.Mode.LOADING : LoadMoreView.Mode.NO_MORE;
            }

            loadMoreView.configure(mode);
            return loadMoreView;
        }

        private LayoutInflater mInflater;
    }

    private Handler mHandler = new Handler();

}