Maintain filtered listview after rotation in android

I'm using customized ListView in android, and using search with customized EditText. When I search for a name, I will get the result using getFilter().filter(cs);. But, when I rotate, the ListView shows the full list (without filtering), then after a delay, it shows the filtered list.

When I rotate without filtering, it maintains the listview position.

So I have to maintain the filtered ListView when I rotate the screen.

Please help. Thanks in advance...

import java.util.ArrayList;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Loader;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.ContactsContract;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.TypedValue;
import android.view.Display;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.Filter;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

public  class       ContactsListActivity 
        extends     Activity 
        implements  LoaderManager.LoaderCallbacks<ArrayList<ListViewItem>> {

    private LetterScrollListView    mLSListView;
    private ProgressBar             mProgressBar;
    private EditText                mSearchText;
    private ProgressBar             mSearchProgressBar;
    private LinearLayout            mViewsLl;
    private ContactAdapter          mFullContactAdapter = null;
    private ArrayList<ListViewItem> mFullContactsArrayList = null;

    public boolean  isSoftKeyOn = false;
    public boolean  isPortrait;

    private long            mLastTimeTextChanged    = 0L;
    private long            mCurrentTime = 0L;
    private Filter          mFilter;

    protected void onCreate(Bundle savedInstanceState) {

        RelativeLayout windowRl = (RelativeLayout) findViewById(;
        LinearLayout progressBarLl = (LinearLayout) windowRl.findViewById(;
        mViewsLl = (LinearLayout) windowRl.findViewById(;
        mSearchText = (EditText) mViewsLl.findViewById(;
        mSearchProgressBar = (ProgressBar) mViewsLl.findViewById(;
        mLSListView = (LetterScrollListView) mViewsLl.findViewById(;
        if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            isPortrait = true;
        } else {
            isPortrait = false;

        final View activityRootView = windowRl;
                new OnGlobalLayoutListener() {
                    public void onGlobalLayout() {
                        int heightDiff = activityRootView.getRootView()
                                .getHeight() - activityRootView.getHeight();
                        // if heightDiff > 100 pixels, its probably a keyboard...
                        if (heightDiff > 100) {
//                          Toast.makeText(getApplicationContext(), "Key ON",
//                                  Toast.LENGTH_SHORT).show();
                            isSoftKeyOn = true;
                        } else {
//                          Toast.makeText(getApplicationContext(), "Key OFF",
//                                  Toast.LENGTH_SHORT).show();
                            isSoftKeyOn = false;

        mSearchText.addTextChangedListener(new TextWatcher() {
            public void onTextChanged(CharSequence cs, int arg1, int arg2,
                    int arg3) {
                mCurrentTime = System.currentTimeMillis();              
                if( (mCurrentTime - mLastTimeTextChanged) <= USER_TYPE_DELAY ) {

                // preparing message
                Bundle bundle = new Bundle();
                bundle.putCharSequence(USER_INPUT_KEY, cs);
                Message message = mSearchInputHandler.obtainMessage(WHAT_SEARCH);

                mSearchInputHandler.sendMessageDelayed(message, USER_TYPE_DELAY);
                mLastTimeTextChanged = mCurrentTime;

            public void beforeTextChanged(CharSequence arg0, int arg1,
                    int arg2, int arg3) {
                // TODO Auto-generated method stub

            public void afterTextChanged(Editable arg0) {
                // TODO Auto-generated method stub

        // Create a progress bar to display while the list loads
        mProgressBar = new ProgressBar(this);

        getLoaderManager().initLoader(0, null, this).forceLoad();

    private final Handler mSearchInputHandler = new Handler() {
        public void handleMessage(Message msg) {
            CharSequence cs = msg.getData().getCharSequence(USER_INPUT_KEY);
            int what = msg.what;

            switch(what) {
            case WHAT_SEARCH:

                // When user changed the Text after a delay


    public void removeSearchProgressBar() {

     * Called when a new Loader needs to be created 
    public Loader<ArrayList<ListViewItem>> onCreateLoader(int id, Bundle args) {
        // Now create and return a CursorLoader that will take care of
        // creating a Cursor for the data being displayed.
        Uri uri = ContactsContract.Contacts.CONTENT_URI;
        String[] projection = new String[] {
        boolean showInvisible = false;
        String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '" +
                (showInvisible ? "0" : "1") + "'";
        String[] selectionArgs = null;
        String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
        return new ContactArrayListLoader(this, uri, projection, selection, selectionArgs, sortOrder);

     * Called when a previously created loader has finished loading 
    public void onLoadFinished(Loader<ArrayList<ListViewItem>> loader, ArrayList<ListViewItem> data) {

        if(mLSListView.getAdapter() == null) {
            mFullContactsArrayList = data;
            mFullContactAdapter = new ContactAdapter(this, R.layout.contact_tuple, mFullContactsArrayList);
            mFilter = mFullContactAdapter.getFilter();

     * Called when a previously created loader is reset, making the data unavailable
    public void onLoaderReset(Loader<ArrayList<ListViewItem>> loader) {
        // This is called when the last Cursor provided to onLoadFinished()
        // above is about to be closed. We need to make sure we are no
        // longer using it.
        //////mListView.setAdapter(new ContactAdapter(this, R.layout.contact_tuple, null));



The problem is on the method

public void onLoadFinished(Loader<ArrayList<ListViewItem>> loader, ArrayList<ListViewItem> data) {....}

On rotation/starting the app, the parameter data in this method is always the complete list and not the filtered list. So to get the filtered list on rotation, just create a static member

private static ArrayList<ListViewItem>  sCurrentContactsArrayList = null;

and save before screen rotation like this:

protected void onSaveInstanceState(Bundle outState) {
    if( TextUtils.isEmpty(mSearchText.getText()) ) {
        sCurrentContactsArrayList = null;
    } else {
        sCurrentContactsArrayList = mFullContactAdapter.getCurrentItems();

also modify onLoadFinished():

public void onLoadFinished(Loader<ArrayList<ListViewItem>> loader, ArrayList<ListViewItem> data) {

    if(mLSListView.getAdapter() == null) {
        ArrayList<ListViewItem> contactsAL = null;
        if(sCurrentContactsArrayList == null) {
            contactsAL = data;
        } else {
            contactsAL = sCurrentContactsArrayList;
        mFullContactAdapter = new ContactAdapter(this, R.layout.contact_tuple, contactsAL, data);
        if(mFilter == null) mFilter = mFullContactAdapter.getFilter();

Need Your Help

Updating listview android on textchanged StringIndexOutOfBoundsException

android listview textchanged

I'm having trouble with updating my listview ontextchanged. When I enter one letter works fine, but on the second letter the app crashes. What can be the problem?

How to encode video from multiple cameras into one mkv stream?

java c++ c mkv

How to encode multiple video and audio streams (we want streams not to be any how encoded) from cameras into one mkv so, that sound from camera A is encoded with respect to video from camera A, using