de.vanita5.twittnuker.fragment.support.UserListFragment.java Source code

Java tutorial

Introduction

Here is the source code for de.vanita5.twittnuker.fragment.support.UserListFragment.java

Source

/*
 * Twittnuker - Twitter client for Android
 *
 * Copyright (C) 2013-2014 vanita5 <mail@vanita5.de>
 *
 * This program incorporates a modified version of Twidere.
 * Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package de.vanita5.twittnuker.fragment.support;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.CardView;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;

import de.vanita5.twittnuker.R;
import de.vanita5.twittnuker.activity.iface.IThemedActivity;
import de.vanita5.twittnuker.activity.support.UserListSelectorActivity;
import de.vanita5.twittnuker.adapter.support.SupportTabsAdapter;
import de.vanita5.twittnuker.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback;
import de.vanita5.twittnuker.fragment.iface.SupportFragmentCallback;
import de.vanita5.twittnuker.model.ParcelableUser;
import de.vanita5.twittnuker.model.ParcelableUserList;
import de.vanita5.twittnuker.model.SingleResponse;
import de.vanita5.twittnuker.util.AsyncTwitterWrapper;
import de.vanita5.twittnuker.util.ImageLoaderWrapper;
import de.vanita5.twittnuker.util.OnLinkClickHandler;
import de.vanita5.twittnuker.util.ParseUtils;
import de.vanita5.twittnuker.util.ThemeUtils;
import de.vanita5.twittnuker.util.TwidereLinkify;
import de.vanita5.twittnuker.util.UserColorNameUtils;
import de.vanita5.twittnuker.util.Utils;
import de.vanita5.twittnuker.view.ColorLabelLinearLayout;
import de.vanita5.twittnuker.view.HeaderDrawerLayout;
import de.vanita5.twittnuker.view.HeaderDrawerLayout.DrawerCallback;
import de.vanita5.twittnuker.view.TabPagerIndicator;

import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.UserList;

import static android.text.TextUtils.isEmpty;
import static de.vanita5.twittnuker.util.Utils.getAccountColor;
import static de.vanita5.twittnuker.util.Utils.getTwitterInstance;
import static de.vanita5.twittnuker.util.Utils.openUserProfile;
import static de.vanita5.twittnuker.util.Utils.setMenuItemAvailability;

public class UserListFragment extends BaseSupportFragment
        implements OnClickListener, LoaderCallbacks<SingleResponse<ParcelableUserList>>, DrawerCallback,
        SystemWindowsInsetsCallback, SupportFragmentCallback {

    private ImageLoaderWrapper mProfileImageLoader;
    private AsyncTwitterWrapper mTwitterWrapper;

    private ImageView mProfileImageView;
    private TextView mListNameView, mCreatedByView, mDescriptionView, mErrorMessageView;
    private View mErrorRetryContainer, mProgressContainer;
    private ColorLabelLinearLayout mUserListDetails;
    private Button mRetryButton;
    private HeaderDrawerLayout mHeaderDrawerLayout;
    private ViewPager mViewPager;
    private TabPagerIndicator mPagerIndicator;
    private CardView mCardView;

    private SupportTabsAdapter mPagerAdapter;

    private ParcelableUserList mUserList;
    private final BroadcastReceiver mStatusReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(final Context context, final Intent intent) {
            if (getActivity() == null || !isAdded() || isDetached())
                return;
            final String action = intent.getAction();
            final ParcelableUserList userList = intent.getParcelableExtra(EXTRA_USER_LIST);
            if (userList == null || mUserList == null)
                return;
            if (BROADCAST_USER_LIST_DETAILS_UPDATED.equals(action)) {
                if (userList.id == mUserList.id) {
                    getUserListInfo(true);
                }
            } else if (BROADCAST_USER_LIST_SUBSCRIBED.equals(action)
                    || BROADCAST_USER_LIST_UNSUBSCRIBED.equals(action)) {
                if (userList.id == mUserList.id) {
                    getUserListInfo(true);
                }
            }
        }
    };
    private boolean mUserListLoaderInitialized;
    private Fragment mCurrentVisibleFragment;

    @Override
    public boolean canScroll(float dy) {
        final Fragment fragment = mCurrentVisibleFragment;
        return fragment instanceof DrawerCallback && ((DrawerCallback) fragment).canScroll(dy);
    }

    @Override
    public void cancelTouch() {
        final Fragment fragment = mCurrentVisibleFragment;
        if (fragment instanceof DrawerCallback) {
            ((DrawerCallback) fragment).cancelTouch();
        }
    }

    @Override
    public void fling(float velocity) {
        final Fragment fragment = mCurrentVisibleFragment;
        if (fragment instanceof DrawerCallback) {
            ((DrawerCallback) fragment).fling(velocity);
        }
    }

    @Override
    public boolean isScrollContent(float x, float y) {
        final ViewPager v = mViewPager;
        final int[] location = new int[2];
        v.getLocationOnScreen(location);
        return x >= location[0] && x <= location[0] + v.getWidth() && y >= location[1]
                && y <= location[1] + v.getHeight();
    }

    @Override
    public void scrollBy(float dy) {
        final Fragment fragment = mCurrentVisibleFragment;
        if (fragment instanceof DrawerCallback) {
            ((DrawerCallback) fragment).scrollBy(dy);
        }
    }

    @Override
    public boolean shouldLayoutHeaderBottom() {
        final HeaderDrawerLayout drawer = mHeaderDrawerLayout;
        final CardView card = mCardView;
        if (drawer == null || card == null)
            return false;
        return card.getTop() + drawer.getHeaderTop() - drawer.getPaddingTop() <= 0;
    }

    @Override
    public void topChanged(int offset) {

    }

    public void displayUserList(final ParcelableUserList userList) {
        if (userList == null || getActivity() == null)
            return;
        getLoaderManager().destroyLoader(0);
        mErrorRetryContainer.setVisibility(View.GONE);
        mProgressContainer.setVisibility(View.GONE);
        mUserList = userList;
        mUserListDetails.drawEnd(getAccountColor(getActivity(), userList.account_id));
        mListNameView.setText(userList.name);
        final String displayName = UserColorNameUtils.getDisplayName(getActivity(), userList.user_name,
                userList.user_screen_name);
        mCreatedByView.setText(getString(R.string.created_by, displayName));
        final String description = userList.description;
        mDescriptionView.setVisibility(isEmpty(description) ? View.GONE : View.VISIBLE);
        mDescriptionView.setText(description);
        final TwidereLinkify linkify = new TwidereLinkify(
                new OnLinkClickHandler(getActivity(), getMultiSelectManager()));
        linkify.applyAllLinks(mDescriptionView, userList.account_id, false);
        mDescriptionView.setMovementMethod(LinkMovementMethod.getInstance());
        mProfileImageLoader.displayProfileImage(mProfileImageView, userList.user_profile_image_url);
        invalidateOptionsMenu();
    }

    @Override
    public Fragment getCurrentVisibleFragment() {
        return mCurrentVisibleFragment;
    }

    @Override
    public void onDetachFragment(Fragment fragment) {

    }

    @Override
    public void onSetUserVisibleHint(Fragment fragment, boolean isVisibleToUser) {
        mCurrentVisibleFragment = isVisibleToUser ? fragment : null;
    }

    @Override
    public boolean triggerRefresh(int position) {
        return false;
    }

    @Override
    public boolean getSystemWindowsInsets(Rect insets) {
        return false;
    }

    public void getUserListInfo(final boolean omit_intent_extra) {
        final LoaderManager lm = getLoaderManager();
        lm.destroyLoader(0);
        final Bundle args = new Bundle(getArguments());
        args.putBoolean(EXTRA_OMIT_INTENT_EXTRA, omit_intent_extra);
        if (!mUserListLoaderInitialized) {
            lm.initLoader(0, args, this);
            mUserListLoaderInitialized = true;
        } else {
            lm.restartLoader(0, args, this);
        }
    }

    @Override
    public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
        switch (requestCode) {
        case REQUEST_SELECT_USER: {
            if (resultCode != Activity.RESULT_OK || !data.hasExtra(EXTRA_USER) || mTwitterWrapper == null
                    || mUserList == null)
                return;
            final ParcelableUser user = data.getParcelableExtra(EXTRA_USER);
            mTwitterWrapper.addUserListMembersAsync(mUserList.account_id, mUserList.id, user);
            return;
        }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
            final Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_user_list, container, false);
    }

    @Override
    public void onActivityCreated(final Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setHasOptionsMenu(true);

        final FragmentActivity activity = getActivity();

        mHeaderDrawerLayout.setDrawerCallback(this);

        mPagerAdapter = new SupportTabsAdapter(activity, getChildFragmentManager());

        mViewPager.setAdapter(mPagerAdapter);
        mPagerIndicator.setViewPager(mViewPager);
        mPagerIndicator.setTabDisplayOption(TabPagerIndicator.LABEL);
        if (activity instanceof IThemedActivity) {
            mPagerIndicator.setStripColor(((IThemedActivity) activity).getCurrentThemeColor());
        } else {

        }

        mTwitterWrapper = getApplication().getTwitterWrapper();
        mProfileImageLoader = getApplication().getImageLoaderWrapper();
        mProfileImageView.setOnClickListener(this);
        mUserListDetails.setOnClickListener(this);
        mRetryButton.setOnClickListener(this);
        getUserListInfo(false);

        setupUserPages();
    }

    @Override
    public void onStart() {
        super.onStart();
        final IntentFilter filter = new IntentFilter(BROADCAST_USER_LIST_DETAILS_UPDATED);
        filter.addAction(BROADCAST_USER_LIST_SUBSCRIBED);
        filter.addAction(BROADCAST_USER_LIST_UNSUBSCRIBED);
        registerReceiver(mStatusReceiver, filter);
    }

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

    @Override
    public void onDestroyView() {
        mUserList = null;
        getLoaderManager().destroyLoader(0);
        super.onDestroyView();
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.menu_user_list, menu);
    }

    @Override
    public void onPrepareOptionsMenu(Menu menu) {
        final AsyncTwitterWrapper twitter = getTwitterWrapper();
        final ParcelableUserList userList = mUserList;
        final MenuItem followItem = menu.findItem(MENU_FOLLOW);
        if (followItem != null) {
            followItem.setEnabled(userList != null);
            if (userList == null) {
                followItem.setIcon(android.R.color.transparent);
            }
        }
        if (twitter == null || userList == null)
            return;
        final boolean isMyList = userList.user_id == userList.account_id;
        setMenuItemAvailability(menu, MENU_EDIT, isMyList);
        setMenuItemAvailability(menu, MENU_ADD, isMyList);
        setMenuItemAvailability(menu, MENU_DELETE, isMyList);
        final boolean isFollowing = userList.is_following;
        if (followItem != null) {
            followItem.setVisible(!isMyList);
            if (isFollowing) {
                followItem.setIcon(R.drawable.ic_action_cancel);
                followItem.setTitle(R.string.unsubscribe);
            } else {
                followItem.setIcon(R.drawable.ic_action_add);
                followItem.setTitle(R.string.subscribe);
            }
        }
    }

    @Override
    public boolean onOptionsItemSelected(final MenuItem item) {
        final AsyncTwitterWrapper twitter = getTwitterWrapper();
        final ParcelableUserList userList = mUserList;
        if (twitter == null || userList == null)
            return false;
        switch (item.getItemId()) {
        case MENU_ADD: {
            if (userList.user_id != userList.account_id)
                return false;
            final Intent intent = new Intent(INTENT_ACTION_SELECT_USER);
            intent.setClass(getActivity(), UserListSelectorActivity.class);
            intent.putExtra(EXTRA_ACCOUNT_ID, userList.account_id);
            startActivityForResult(intent, REQUEST_SELECT_USER);
            break;
        }
        case MENU_DELETE: {
            if (userList.user_id != userList.account_id)
                return false;
            DestroyUserListDialogFragment.show(getFragmentManager(), userList);
            break;
        }
        case MENU_EDIT: {
            final Bundle args = new Bundle();
            args.putLong(EXTRA_ACCOUNT_ID, userList.account_id);
            args.putString(EXTRA_LIST_NAME, userList.name);
            args.putString(EXTRA_DESCRIPTION, userList.description);
            args.putBoolean(EXTRA_IS_PUBLIC, userList.is_public);
            args.putLong(EXTRA_LIST_ID, userList.id);
            final DialogFragment f = new EditUserListDialogFragment();
            f.setArguments(args);
            f.show(getFragmentManager(), "edit_user_list_details");
            return true;
        }
        case MENU_FOLLOW: {
            if (userList.is_following) {
                DestroyUserListSubscriptionDialogFragment.show(getFragmentManager(), userList);
            } else {
                twitter.createUserListSubscriptionAsync(userList.account_id, userList.id);
            }
            return true;
        }
        default: {
            if (item.getIntent() != null) {
                try {
                    startActivity(item.getIntent());
                } catch (final ActivityNotFoundException e) {
                    if (Utils.isDebugBuild())
                        Log.w(LOGTAG, e);
                    return false;
                }
            }
            break;
        }
        }
        return true;
    }

    @Override
    public void onClick(final View view) {
        switch (view.getId()) {
        case R.id.retry: {
            getUserListInfo(true);
            break;
        }
        case R.id.profile_image: {
            if (mUserList == null)
                return;
            openUserProfile(getActivity(), mUserList.account_id, mUserList.user_id, mUserList.user_screen_name,
                    null);
            break;
        }
        }

    }

    @Override
    public Loader<SingleResponse<ParcelableUserList>> onCreateLoader(final int id, final Bundle args) {
        mErrorMessageView.setText(null);
        mErrorMessageView.setVisibility(View.GONE);
        mErrorRetryContainer.setVisibility(View.GONE);
        mHeaderDrawerLayout.setVisibility(View.GONE);
        mProgressContainer.setVisibility(View.VISIBLE);
        setProgressBarIndeterminateVisibility(true);
        final long accountId = args != null ? args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
        final long userId = args != null ? args.getLong(EXTRA_USER_ID, -1) : -1;
        final int listId = args != null ? args.getInt(EXTRA_LIST_ID, -1) : -1;
        final String listName = args != null ? args.getString(EXTRA_LIST_NAME) : null;
        final String screenName = args != null ? args.getString(EXTRA_SCREEN_NAME) : null;
        final boolean omitIntentExtra = args == null || args.getBoolean(EXTRA_OMIT_INTENT_EXTRA, true);
        return new ParcelableUserListLoader(getActivity(), omitIntentExtra, getArguments(), accountId, listId,
                listName, userId, screenName);
    }

    @Override
    public void onLoadFinished(final Loader<SingleResponse<ParcelableUserList>> loader,
            final SingleResponse<ParcelableUserList> data) {
        if (data == null)
            return;
        if (getActivity() == null)
            return;
        if (data.getData() != null) {
            final ParcelableUserList list = data.getData();
            displayUserList(list);
            mHeaderDrawerLayout.setVisibility(View.VISIBLE);
            mErrorRetryContainer.setVisibility(View.GONE);
            mProgressContainer.setVisibility(View.GONE);
        } else {
            if (data.hasException()) {
                mErrorMessageView.setText(data.getException().getMessage());
                mErrorMessageView.setVisibility(View.VISIBLE);
            }
            mHeaderDrawerLayout.setVisibility(View.GONE);
            mErrorRetryContainer.setVisibility(View.VISIBLE);
            mProgressContainer.setVisibility(View.GONE);
        }
        setProgressBarIndeterminateVisibility(false);
    }

    @Override
    public void onLoaderReset(final Loader<SingleResponse<ParcelableUserList>> loader) {

    }

    @Override
    public void onViewCreated(final View view, final Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mHeaderDrawerLayout = (HeaderDrawerLayout) view.findViewById(R.id.details_container);
        mErrorRetryContainer = view.findViewById(R.id.error_retry_container);
        mProgressContainer = view.findViewById(R.id.progress_container);

        final View headerView = mHeaderDrawerLayout.getHeader();
        final View contentView = mHeaderDrawerLayout.getContent();
        mCardView = (CardView) headerView.findViewById(R.id.card);
        mUserListDetails = (ColorLabelLinearLayout) headerView.findViewById(R.id.user_list_details);
        mListNameView = (TextView) headerView.findViewById(R.id.list_name);
        mCreatedByView = (TextView) headerView.findViewById(R.id.created_by);
        mDescriptionView = (TextView) headerView.findViewById(R.id.description);
        mProfileImageView = (ImageView) headerView.findViewById(R.id.profile_image);
        mRetryButton = (Button) mErrorRetryContainer.findViewById(R.id.retry);
        mErrorMessageView = (TextView) mErrorRetryContainer.findViewById(R.id.error_message);
        mViewPager = (ViewPager) contentView.findViewById(R.id.view_pager);
        mPagerIndicator = (TabPagerIndicator) contentView.findViewById(R.id.view_pager_tabs);
    }

    @Override
    protected void fitSystemWindows(Rect insets) {
        super.fitSystemWindows(insets);
        final View progress = mProgressContainer, error = mErrorRetryContainer;
        final HeaderDrawerLayout content = mHeaderDrawerLayout;
        if (progress == null || error == null || content == null) {
            return;
        }
        progress.setPadding(insets.left, insets.top, insets.right, insets.bottom);
        error.setPadding(insets.left, insets.top, insets.right, insets.bottom);
        content.setPadding(insets.left, insets.top, insets.right, insets.bottom);
        content.setClipToPadding(false);
    }

    private void setupUserPages() {
        final Context context = getActivity();
        final Bundle args = getArguments(), tabArgs = new Bundle();
        if (args.containsKey(EXTRA_USER)) {
            final ParcelableUserList userList = args.getParcelable(EXTRA_USER_LIST);
            tabArgs.putLong(EXTRA_ACCOUNT_ID, userList.account_id);
            tabArgs.putLong(EXTRA_USER_ID, userList.user_id);
            tabArgs.putString(EXTRA_SCREEN_NAME, userList.user_screen_name);
            tabArgs.putInt(EXTRA_LIST_ID, (int) userList.id);
            tabArgs.putString(EXTRA_LIST_NAME, userList.name);
        } else {
            tabArgs.putLong(EXTRA_ACCOUNT_ID, args.getLong(EXTRA_ACCOUNT_ID, -1));
            tabArgs.putLong(EXTRA_USER_ID, args.getLong(EXTRA_USER_ID, -1));
            tabArgs.putString(EXTRA_SCREEN_NAME, args.getString(EXTRA_SCREEN_NAME));
            tabArgs.putInt(EXTRA_LIST_ID, args.getInt(EXTRA_LIST_ID, -1));
            tabArgs.putString(EXTRA_LIST_NAME, args.getString(EXTRA_LIST_NAME));
        }
        mPagerAdapter.addTab(UserListTimelineFragment.class, tabArgs, getString(R.string.statuses), null, 0);
        mPagerAdapter.addTab(UserListMembersFragment.class, tabArgs, getString(R.string.members), null, 1);
        mPagerAdapter.addTab(UserListSubscribersFragment.class, tabArgs, getString(R.string.subscribers), null, 2);
        mPagerIndicator.notifyDataSetChanged();
    }

    public static class EditUserListDialogFragment extends BaseSupportDialogFragment
            implements DialogInterface.OnClickListener {

        private EditText mEditName, mEditDescription;
        private CheckBox mPublicCheckBox;
        private String mName, mDescription;
        private long mAccountId;
        private long mListId;
        private boolean mIsPublic;
        private AsyncTwitterWrapper mTwitterWrapper;

        @Override
        public void onClick(final DialogInterface dialog, final int which) {
            if (mAccountId <= 0)
                return;
            switch (which) {
            case DialogInterface.BUTTON_POSITIVE: {
                mName = ParseUtils.parseString(mEditName.getText());
                mDescription = ParseUtils.parseString(mEditDescription.getText());
                mIsPublic = mPublicCheckBox.isChecked();
                if (mName == null || mName.length() <= 0)
                    return;
                mTwitterWrapper.updateUserListDetails(mAccountId, mListId, mIsPublic, mName, mDescription);
                break;
            }
            }

        }

        @NonNull
        @Override
        public Dialog onCreateDialog(final Bundle savedInstanceState) {
            mTwitterWrapper = getApplication().getTwitterWrapper();
            final Bundle bundle = savedInstanceState == null ? getArguments() : savedInstanceState;
            mAccountId = bundle != null ? bundle.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
            mListId = bundle != null ? bundle.getLong(EXTRA_LIST_ID, -1) : -1;
            mName = bundle != null ? bundle.getString(EXTRA_LIST_NAME) : null;
            mDescription = bundle != null ? bundle.getString(EXTRA_DESCRIPTION) : null;
            mIsPublic = bundle == null || bundle.getBoolean(EXTRA_IS_PUBLIC, true);
            final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
            final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
            final View view = LayoutInflater.from(wrapped).inflate(R.layout.edit_user_list_detail, null);
            builder.setView(view);
            mEditName = (EditText) view.findViewById(R.id.name);
            mEditDescription = (EditText) view.findViewById(R.id.description);
            mPublicCheckBox = (CheckBox) view.findViewById(R.id.is_public);
            if (mName != null) {
                mEditName.setText(mName);
            }
            if (mDescription != null) {
                mEditDescription.setText(mDescription);
            }
            mPublicCheckBox.setChecked(mIsPublic);
            builder.setTitle(R.string.user_list);
            builder.setPositiveButton(android.R.string.ok, this);
            builder.setNegativeButton(android.R.string.cancel, this);
            return builder.create();
        }

        @Override
        public void onSaveInstanceState(final Bundle outState) {
            outState.putLong(EXTRA_ACCOUNT_ID, mAccountId);
            outState.putLong(EXTRA_LIST_ID, mListId);
            outState.putString(EXTRA_LIST_NAME, mName);
            outState.putString(EXTRA_DESCRIPTION, mDescription);
            outState.putBoolean(EXTRA_IS_PUBLIC, mIsPublic);
            super.onSaveInstanceState(outState);
        }

    }

    static class ParcelableUserListLoader extends AsyncTaskLoader<SingleResponse<ParcelableUserList>> {

        private final boolean mOmitIntentExtra;
        private final Bundle mExtras;
        private final long mAccountId, mUserId;
        private final int mListId;
        private final String mScreenName, mListName;

        private ParcelableUserListLoader(final Context context, final boolean omitIntentExtra, final Bundle extras,
                final long accountId, final int listId, final String listName, final long userId,
                final String screenName) {
            super(context);
            mOmitIntentExtra = omitIntentExtra;
            mExtras = extras;
            mAccountId = accountId;
            mUserId = userId;
            mListId = listId;
            mScreenName = screenName;
            mListName = listName;
        }

        @Override
        public SingleResponse<ParcelableUserList> loadInBackground() {
            if (!mOmitIntentExtra && mExtras != null) {
                final ParcelableUserList cache = mExtras.getParcelable(EXTRA_USER_LIST);
                if (cache != null)
                    return SingleResponse.getInstance(cache);
            }
            final Twitter twitter = getTwitterInstance(getContext(), mAccountId, true);
            if (twitter == null)
                return SingleResponse.getInstance();
            try {
                final UserList list;
                if (mListId > 0) {
                    list = twitter.showUserList(mListId);
                } else if (mUserId > 0) {
                    list = twitter.showUserList(mListName, mUserId);
                } else if (mScreenName != null) {
                    list = twitter.showUserList(mListName, mScreenName);
                } else
                    return SingleResponse.getInstance();
                return SingleResponse.getInstance(new ParcelableUserList(list, mAccountId));
            } catch (final TwitterException e) {
                return SingleResponse.getInstance(e);
            }
        }

        @Override
        public void onStartLoading() {
            forceLoad();
        }

    }

}