English 中文(简体)
Android 4.0.3 光标天体设计师对变化光谱不弹射 ListView 。
原标题:Android 4.0.3 CursorAdapter doesn t populate ListView on changeCursor
  • 时间:2012-05-24 16:41:46
  •  标签:
  • android

我没有为这个对话框发布我的 XML 。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/tag_layout"
    android:orientation="vertical"
    android:layout_height="wrap_content"
    android:layout_width="@dimen/min_dialog_width"
    android:padding="5dp"
    android:animateLayoutChanges="true"
    >

<!-- Here is the view to show if the list is emtpy -->
<TextView
        android:id="@android:id/empty"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="50dp"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:text="@string/no_items"
        android:visibility="invisible"
        />

<ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:visibility="invisible"
        />

<ProgressBar
        android:id="@+id/tag_spin_progress_bar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:indeterminate="true"
        />

</RelativeLayout>

我使用机器人.support.v4.Cursor Loader 和 CursorAdapter, 我正试图让它更新光标。 在 Android 2.3.3 中,它的工作很好。 但是当我在我的4.0.3 设备上尝试它时, ListView 并不更新, 我的适配器中的新View 方法从未被调用过。 我知道光标有数据, 因为我可以在我的2.3.3 设备上看到它 。

如果我旋转我的设备, ListView 将显示我想要的东西。 我尝试取消 ListView, 但无法解决问题 。

如果我不重置 ListView 的适配器, 列表不会变成空白, 但是仍然无法刷新列表 。

我所做的这一切 在一个延伸的AwardDialog内 嵌入一个对话的碎片。

这是整个班的全班

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Resources;
import android.database.Cursor;
import android.os.Bundle;

import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;

import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.*;
import org.lds.ldssa.service.MLDatabase;
import org.lds.ldssa.service.aws.Annotation;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class TagDialog extends AlertDialog implements LoaderManager.LoaderCallbacks<Cursor>,AdapterView.OnItemClickListener {

private static final String TAG = "ldssa.tagdialog";
public static final int TAGLOADERID = 0;

// View Items
private EditText mEditText;
private ListView mListView;
private TextView mEmptyView;
private ProgressBar mProgressBar;
private ImageButton mNewTagButton;
private ImageButton mSortTagButton;
private TextView mTitle;
private String mTagTitle;
private String mNewTagTitle;

private Annotation mAnnotation;
private ContentFragment mContentFragment;

private boolean isNewTagView;
private static final String KEY_NEWTAGVIEW = "new_tag_view";

private static final String POSITION_KEY = "TAG_POSITION";
private static final String Y_KEY = "TAG_Y";
private static final String SORT_KEY = "TAG_SORT";
private static final String CHECKED_STATE_KEY = "TAG_CHECKED_STATE";
private static final int NOT_SET = -1;
private int mPosition;
private int mY;

private TagSuggestionAdapter mSuggestionAdapter;
private TagListAdapter mTagAdapter;

private MLDatabase mlDatabase;
private boolean mSortAlpha;
private HashMap<Long, CheckedState> mCheckedState;

protected TagDialog(Context context) {
    super(context);
}

public void onCreate(Bundle savedInstanceState){
    Context context = getContext();
    Resources r = context.getResources();

    final LayoutInflater inflater = LayoutInflater.from(context);
    View view = inflater.inflate(R.layout.dialog_tag, null);

    // Main parts of the view        
    mEditText = (EditText) view.findViewById(R.id.tag_new_tag);
    mListView = (ListView) view.findViewById(android.R.id.list);
    mProgressBar = (ProgressBar) view.findViewById(R.id.tag_spin_progress_bar);
    mEmptyView = (TextView) view.findViewById(android.R.id.empty);
    mEmptyView.setVisibility(View.INVISIBLE);

    // Titlebar
    View titleBar = inflater.inflate(R.layout.dialog_tag_title, null);
    mNewTagButton = (ImageButton) titleBar.findViewById(R.id.tag_new_icon);
    mSortTagButton = (ImageButton) titleBar.findViewById(R.id.tag_sort_icon);
    mTitle = (TextView) titleBar.findViewById(R.id.tag_title);
    mTagTitle = r.getString(R.string.tag_dialog_title);
    mNewTagTitle = r.getString(R.string.tag_new_dialog_title);
    this.setCustomTitle(titleBar);

    // Buttons
    final String OK = r.getString(R.string.ok);
    final String CANCEL = r.getString(R.string.cancel);
    this.setButton(BUTTON_POSITIVE, OK, new OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) { /*Never Used*/}});
    this.setButton(BUTTON_NEGATIVE, CANCEL, new OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) { /*Never Used*/}});

    // Setup Button Listeners
    setOnShowListener(new OnShowListener() {
        @Override
        public void onShow(DialogInterface dialog) {
            Button ok = getButton(BUTTON_POSITIVE);
            ok.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(isNewTagView){
                        hideIMM();
                        addNewTag();
                        mEditText.setText("");
                        setupTagDialog();
                    } else {
                        Collection<CheckedState> changes = mCheckedState.values();
                        boolean success = true;
                        MLDatabase db = getDatabase();
                        db.beginAnnotationTransaction();
                        for(CheckedState change : changes){
                            if(!change.checked()){
                                //Detag
                                db.detagAnnotation(mAnnotation.getDbKey(), change.tagID());
                            } else {
                                mAnnotation.saveHighlightsToDatabase(db);
                                if(mAnnotation.getDbKey().intValue() != MLDatabase.NOT_SET_INT &
                                        change.tagID() != MLDatabase.NOT_SET_INT){
                                    success = db.tagAnnotation(mAnnotation.getDbKey(), change.tagID(), change.changed());
                                }
                            }
                        }
                        if(success){
                            db.setAnnotationTransactionSuccessful();
                        }
                        db.endAnnotationTransaction();
                        mCheckedState.clear();
                        dismiss();
                    }
                }
            });

            Button cancel = getButton(BUTTON_NEGATIVE);
            cancel.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(isNewTagView){
                        hideIMM();
                        setupTagDialog();
                        mEditText.setText("");
                    } else {
                        mCheckedState.clear();
                        dismiss();
                    }
                }
            });
        }
    });

    mNewTagButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            setupNewTagDialog();
        }
    });
    mSortTagButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mSortAlpha = !mSortAlpha;
            restartLoader();
        }
    });

    mListView.setOnItemClickListener(TagDialog.this);

    mEditText.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {}

        @Override
        public void afterTextChanged(Editable s) {
           LoaderManager lm = getLoaderManager();
            if(lm != null){
                Loader l = lm.getLoader(TAGLOADERID);
                if(l != null){
                    l.forceLoad();
                } else {
                    restartLoader();
                }
            } else {
                restartLoader();
            }
        }
    });

    //Handle Rotations
    if(savedInstanceState == null){
        //New
        mPosition = NOT_SET;
        mY = NOT_SET;
        mSortAlpha = false;
        mCheckedState = getCheckedState(mAnnotation.getDbKey());
        isNewTagView = false;
    } else {
        //rotated
        isNewTagView = savedInstanceState.getBoolean(KEY_NEWTAGVIEW, false);
        mPosition = savedInstanceState.getInt(POSITION_KEY, NOT_SET);
        mY = savedInstanceState.getInt(Y_KEY, NOT_SET);
        mSortAlpha = savedInstanceState.getBoolean(SORT_KEY, false);
        restoreCheckedState(savedInstanceState);
    }

    mTagAdapter = new TagListAdapter(context, null, mCheckedState);
    mSuggestionAdapter = new TagSuggestionAdapter(context, null, 0);

    LoaderManager lm = getLoaderManager();
    if(lm != null){
        lm.initLoader(TAGLOADERID, null, this);
    }

    this.setView(view);
    super.onCreate(savedInstanceState);
}

private void addNewTag() {
    String tag = mEditText.getText().toString().trim();
    if(!tag.equals("")){
        getDatabase();
        Integer langID = mAnnotation.getLanguageId();
        try{
            long tagID = mlDatabase.insertTag(langID, tag);
            if(mAnnotation.getDbKey().intValue() != MLDatabase.NOT_SET_INT &&
                    tagID != MLDatabase.NOT_SET_INT){
                mCheckedState.put(tagID, new CheckedState(tagID, true, true));
            }
        } catch (Exception e) {
            Log.d(TAG, "Problem saving new tag: " + tag + " : " + e.getMessage());
            e.printStackTrace();
        }
    }
}

public void onStart(){
    if(isNewTagView){
        setupNewTagDialog();
    } else {
        setupTagDialog();
    }
    restartLoader();
}

@Override
public Bundle onSaveInstanceState(){
    Bundle bundle = super.onSaveInstanceState();

    //Save What dialog we are in.
    bundle.putBoolean(KEY_NEWTAGVIEW, isNewTagView);
    bundle.putBoolean(SORT_KEY, mSortAlpha);

    //Save position
    bundle.putInt(POSITION_KEY, mListView.getFirstVisiblePosition());
    final View v = mListView.getChildAt(0);
    bundle.putInt(Y_KEY, (v == null) ? 0 : v.getTop());

    //Save Checked State
    Iterator it = mCheckedState.entrySet().iterator();
    int i = 0;
    while(it.hasNext()){
        Map.Entry pair = (Map.Entry)it.next();
        bundle.putSerializable(CHECKED_STATE_KEY + i, (CheckedState)pair.getValue());
        i++;
    }
    bundle.putInt(CHECKED_STATE_KEY, i);

    return bundle;
}

private void restoreCheckedState(Bundle bundle){
    int count = bundle.getInt(CHECKED_STATE_KEY);
    mCheckedState = new HashMap<Long, CheckedState>();
    boolean success = true;
    for(int i = 0; i < count; i++){
        CheckedState cs = (CheckedState)bundle.getSerializable(CHECKED_STATE_KEY+i);
        if(cs == null){
            success = false;
            break;
        }
        mCheckedState.put(cs.tagID(), cs);
    }
    if(!success){
        mCheckedState = getCheckedState(mAnnotation.getDbKey());
    }
}

@Override
public void onBackPressed(){
    if(isNewTagView){
        hideIMM();
        setupTagDialog();
    } else {
        this.dismiss();
    }
}

private void setupTagDialog() {
    isNewTagView = false;
    mTitle.setText(mTagTitle);
    mNewTagButton.setVisibility(View.VISIBLE);
    mSortTagButton.setVisibility(View.VISIBLE);
    mEmptyView.setVisibility(View.INVISIBLE);
    mEditText.setVisibility(View.GONE);
    mListView.setVisibility(View.GONE);
    mProgressBar.setVisibility(View.VISIBLE);
    mListView.setAdapter(mTagAdapter);
    restartLoader();
}

private void setupNewTagDialog() {
    isNewTagView = true;
    mTitle.setText(mNewTagTitle);
    mNewTagButton.setVisibility(View.INVISIBLE);
    mSortTagButton.setVisibility(View.INVISIBLE);
    mEmptyView.setVisibility(View.INVISIBLE);
    mEditText.setVisibility(View.VISIBLE);
    mListView.setVisibility(View.GONE);
    mProgressBar.setVisibility(View.VISIBLE);
    mListView.setAdapter(mSuggestionAdapter);
    restartLoader();
}

public void setAnnotation(Annotation a) {
    mAnnotation = a;
}

public void setContentViewInterface(ContentFragment contentFragment) {
    mContentFragment = contentFragment;
}

private MLDatabase getDatabase() {
    if(mlDatabase == null){
        GospelLibraryApplication app = (GospelLibraryApplication) getContext().getApplicationContext();
        mlDatabase = app.getMlDatabase();
    }
    return mlDatabase;
}

public String getFilter() {
    return mEditText.getText().toString().trim();
}

public Integer getAnnotationID(){
    if(mAnnotation != null){
        return mAnnotation.getDbKey();
    }
    return MLDatabase.NOT_SET_INT;
}

private LoaderManager getLoaderManager(){
    if(mContentFragment == null){
        Log.d(TAG, "ContentFragment is NULL!");
        return null;
    }
    return mContentFragment.getContentActivity().getSupportLoaderManager();
}

private void restartLoader(){
    LoaderManager lm = getLoaderManager();
    if(lm != null){
        lm.restartLoader(TAGLOADERID, null, this);
    }
}

private void hideIMM(){
    InputMethodManager imm = (InputMethodManager)getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
}

private HashMap<Long, CheckedState> getCheckedState(Integer annotationID) {
    HashMap<Long, CheckedState> checkedState = new HashMap<Long, CheckedState>();
    MLDatabase db = getDatabase();
    Cursor cursor = db.queryAllTagsWithAnnotation(annotationID);
    if(cursor != null){
        for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()){
            Long tagID = cursor.getLong(cursor.getColumnIndex(MLDatabase.CL_ID));
            boolean isChecked = !cursor.isNull(cursor.getColumnIndex(MLDatabase.CL_ANNOTATION));
            checkedState.put(tagID, new CheckedState(tagID, isChecked, false));
        }
    }
    return checkedState;
}

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    TagCursorLoader loader = new TagCursorLoader(getContext(), this);
    return loader;
}

@Override
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor data) {
    if(isNewTagView) {
        mSuggestionAdapter.changeCursor(data);
        if(mListView.getAdapter() == null){
            mListView.setAdapter(mSuggestionAdapter);
        }
    } else {
        mTagAdapter.changeCursor(data);
        if(mListView.getAdapter() == null){
            mListView.setAdapter(mTagAdapter);
        }
    }
    if(mPosition != NOT_SET && mY != NOT_SET){
        mListView.setSelectionFromTop(mPosition, mY);
        mPosition = mY = NOT_SET;
    }

    if (mListView.getAdapter() != null) {
        if (mListView.getAdapter().getCount() > 0) {
            mEmptyView.setVisibility(View.INVISIBLE);
        }
        else {
            mEmptyView.setVisibility(View.VISIBLE);
        }
    }
    else {
        mEmptyView.setVisibility(View.VISIBLE);
    }
    mProgressBar.setVisibility(View.GONE);
    mListView.setVisibility(View.VISIBLE);
    mListView.invalidate();
}

@Override
public void onLoaderReset(Loader<Cursor> cursorLoader) {
    if(mSuggestionAdapter != null) {
        mSuggestionAdapter.changeCursor(null);
    }
}

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    if(isNewTagView){
        TextView tv = (TextView)view;
        mEditText.setText(tv.getText());
        Button ok = getButton(BUTTON_POSITIVE);
        if(ok != null){
            ok.performClick();
        }
    } else {
        CheckedTextView ctv = (CheckedTextView)view;
        boolean checked = !ctv.isChecked();
        ctv.setChecked(checked);
        mCheckedState.put(id, new CheckedState(id, checked, true));
    }

}

public static class TagCursorLoader extends CursorLoader {
    private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver();

    private TagDialog dialog;
    private MLDatabase mlDatabase;
    private Cursor mCursor;
    private String mFilter;
    private Integer mAnnotationID;

    // Runs on worker thread
    @Override
    public Cursor loadInBackground(){
        Cursor cursor = null;
        if(dialog.isNewTagView){
            mFilter = dialog.getFilter();
            cursor = mlDatabase.getTagSuggestions(mFilter);
        } else {
            cursor = mlDatabase.queryTags(dialog.mSortAlpha);
        }

        if(cursor != null){
            cursor.registerContentObserver(mObserver);
        }

        return cursor;

    }

    //Runs on UI thread
    @Override
    public void deliverResult(Cursor cursor){
        //Handle if canceled in the middle.
        if(isReset()){
            if(cursor != null){
                cursor.close();
            }
            return;
        }

        Cursor oldCursor = mCursor;
        mCursor = cursor;
        if(isStarted()) {
            super.deliverResult(cursor);
        }

        if(oldCursor != null && !oldCursor.equals(cursor) && !oldCursor.isClosed()) {
            oldCursor.close();
        }
    }

    public TagCursorLoader(Context context, TagDialog dialog) {
        super(context);
        this.dialog = dialog;
        mlDatabase = dialog.getDatabase();
    }

    @Override
    public void onStartLoading(){
        if(mCursor == null) {
            forceLoad();
        } else {
            if(dialog.isNewTagView && mFilter.equals(dialog.getFilter())) {
                deliverResult(mCursor);
            } else {
                forceLoad();
            }
        }
    }

    @Override
    protected void onStopLoading() {
        // Attempt to cancel the current load task if possible.
        cancelLoad();
    }

    @Override
    public void onCanceled(Cursor cursor) {
        if (cursor != null && !cursor.isClosed()) {
            cursor.close();
        }
    }

    @Override
    protected void onReset() {
        super.onReset();

        // Ensure the loader is stopped
        onStopLoading();

        if (mCursor != null && !mCursor.isClosed()) {
            mCursor.close();
        }
        mCursor = null;
    }

}

/**
 * Class is used to store the temporary checked state of the tags.
 */
public class CheckedState implements Serializable {
    private static final long serialVersionUID = 1263560458217339487L;

    /**
     * @serialField
     */
    private long tagID;
    /**
     * @serialField
     */
    private boolean checked;
    /**
     * @serialField
     */
    private boolean changed;

    /**
     * Constructor for CheckedState.
     * @param tagID   The tag ID
     * @param checked The Current Checked State
     * @param changed Ture if changed in the dialog. False if pulling from database.
     */
    public CheckedState(long tagID, boolean checked, boolean changed){
        this.tagID = tagID;
        this.checked = checked;
        this.changed = changed;
    }

    public long tagID(){
        return tagID;
    }

    public boolean checked() {
        return checked;
    }

    public boolean changed() {
        return changed;
    }
  }
}
最佳回答

Note I didn t add my XML before. That is where the issue resides.

andriod:animateLayoutChanges 

与我试图做的事情不起作用。

一旦我把它从XML里拿了出来 它就像一个魅力。

问题回答

在我看到的多数例子中,您创建了您的适配实例一次, 并在您查看创建时将其设置为 ListView , 然后调用 get LoaderManager (). init Loader ()

// Prepare the loader.  Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);

然后,在 on Loadfinished () 方法中,你称为 swapCursor () ,自动刷新 ListView

// This is the Adapter being used to display the list s data.
SimpleCursorAdapter mAdapter;
...

public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    // Swap the new cursor in.  (The framework will take care of closing the
    // old cursor once we return.)
    mAdapter.swapCursor(data);
}

The above code was copied from the Loaders documentation http://developer.android.com/guide/topics/fundamentals/loaders.html

UPDATE: The documentation talks about using Loaders for Activities and Fragments, but doesn t mention using Dialogs. I m guessing that if getLoaderManager() exists you are fine, but if you are not using the LoaderManager and you are running the Loader manually yourself, then I would think that you d need to ensure that when you call swapCursor() or setAdapter() that you are doing this on the UI thread. Sometimes the easiest way to ensure this, is to call

getListView().post(new Runnable() {
   public void run() {
      // so the setAdapter() or swapCursor() here
   }
});

我本人也遇到过一些个案, 我从背景中更新了一个 ListView, 在我旋转设备之前没有反映更新, 因为 UI 线索上没有更新 UI 线索 。





相关问题
Android - ListView fling gesture triggers context menu

I m relatively new to Android development. I m developing an app with a ListView. I ve followed the info in #1338475 and have my app recognizing the fling gesture, but after the gesture is complete, ...

AsyncTask and error handling on Android

I m converting my code from using Handler to AsyncTask. The latter is great at what it does - asynchronous updates and handling of results in the main UI thread. What s unclear to me is how to handle ...

Android intent filter for a particular file extension?

I want to be able to download a file with a particular extension from the net, and have it passed to my application to deal with it, but I haven t been able to figure out the intent filter. The ...

Android & Web: What is the equivalent style for the web?

I am quite impressed by the workflow I follow when developing Android applications: Define a layout in an xml file and then write all the code in a code-behind style. Is there an equivalent style for ...

TiledLayer equivalent in Android [duplicate]

To draw landscapes, backgrounds with patterns etc, we used TiledLayer in J2ME. Is there an android counterpart for that. Does android provide an option to set such tiled patterns in the layout XML?

Using Repo with Msysgit

When following the Android Open Source Project instructions on installing repo for use with Git, after running the repo init command, I run into this error: /c/Users/Andrew Rabon/bin/repo: line ...

Android "single top" launch mode and onNewIntent method

I read in the Android documentation that by setting my Activity s launchMode property to singleTop OR by adding the FLAG_ACTIVITY_SINGLE_TOP flag to my Intent, that calling startActivity(intent) would ...

From Web Development to Android Development

I have pretty good skills in PHP , Mysql and Javascript for a junior developer. If I wanted to try my hand as Android Development do you think I might find it tough ? Also what new languages would I ...

热门标签