数据库更新和adapter.notifyDataSetChanged()后列表视图不更新; [英] Listview not updating after database update and adapter.notifyDataSetChanged();

查看:175
本文介绍了数据库更新和adapter.notifyDataSetChanged()后列表视图不更新;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在浏览网2天媒体链接和tryed的东西很多,但似乎无法弄清楚什么是错。

I was browsing the net for 2 days allready and tryed alot of stuff but can't seem to figure out what is wrong with this.

我还是相当新的Andr​​oid的deevelopment所以我可能错过了一些显而易见的。

I am still fairly new to the Android deevelopment so I probably missed something obvious.

我有一个应用程序女巫用sqllite DATABSE存储一些数据和概念证明这显示在ListView的porpose。我可以将项目添加到列表中,删除它们。

I have an app witch is using a sqllite databse to store some data and for the porpose of this Proof of concept displaying that in a listview. I can add items to the list, delete them.

到目前为止好。我的问题是,当我把它删更新中被称为被删除的DATABSE一列,将其设置为1,然后必须更新列表中选择适配器。它似乎不工作。

So far so good. The problem I have is when I instead of delete update a column in the databse called "deleted" and set it to 1 and then have the adapter to update the list. It seems not to work.

如果我使用DELETE语句它的工作原理。它更新,一切都很好,但我whant要在数据库中删除的项目,但不向他们展示(所以basicly隐藏项)

If I use the delete statement it works. It updates and everything is fine but I whant to have the deleted items in the database but not to show them (So basicly "hiding" items)

如果我检查了数据库本身succeded列的变化,一切都在更新,所以我想这是一个刷新的问题,因为适配器不重新查询数据库什么的那个方向

If I check the database the update itself succeded the column changes and everything so I guess it is a refresh problem because the adapter does not requery the database or something in that direction

列表视图装载机:

public void fillData() {

    if(lw.getAdapter() == null){
        // Fields from the database (projection)
        // Must include the _id column for the adapter to work
        String[] from = new String[] { TodoTable.COLUMN_SUMMARY, TodoTable.COLUMN_ID};
        String where = TodoTable.COLUMN_DELETED + " = ?";


        Cursor cursor = getContentResolver().query(TodoContentProvider.CONTENT_URI,from,where,new String[] {"0"},null);
        // Fields on the UI to which we map
        int[] to = new int[] { R.id.label };

        adapter = new SimpleCursorAdapter(this, R.layout.todo_row, cursor, from,
                to, 0);
        Log.v("Count",Integer.toString(cursor.getCount()));
        lw.setAdapter(adapter);
    }
    else
        adapter.notifyDataSetChanged();
    }

删除functon

Delete functon

@Override
public boolean onContextItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case DELETE_ID:
            /* Code for actual delete
            AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item
                    .getMenuInfo();
            Uri uri = Uri.parse(TodoContentProvider.CONTENT_URI + "/"
                    + info.id);
            getContentResolver().delete(uri, null, null);
            fillData();
            */

            /* Code for update and hide */
            AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item
                    .getMenuInfo();
            Uri uri = Uri.parse(TodoContentProvider.CONTENT_URI + "/"
                    + info.id);
            ContentValues values = new ContentValues();
            values.put(TodoTable.COLUMN_DIRTY, 1);
            values.put(TodoTable.COLUMN_DELETED, 1);
            getContentResolver().update(uri,values,null,null);
            fillData();
            return true;
    }
    return super.onContextItemSelected(item);
}

如果我放一个记录到的ContentProvider的查询功能,它实际上不火。

if I put a log to the ContentProvider's query function it actually does not fire.

如何算出这个有什么建议?

Any suggestions on how to figure this out?

如果我用 adapter.swapCursor(光标); 它工作正常,只是只是不知道这是否是这样做的正确方法

If I use adapter.swapCursor(cursor); it works fine just just don't know if this is the correct way of doing this.

public void fillData() {

    // Fields from the database (projection)
    // Must include the _id column for the adapter to work
    String[] from = new String[] { TodoTable.COLUMN_SUMMARY, TodoTable.COLUMN_ID};
    String where = TodoTable.COLUMN_DELETED + " = ?";

    Cursor cursor = getContentResolver().query(TodoContentProvider.CONTENT_URI,from,where,new String[] {"0"},null);

    // Fields on the UI to which we map
    int[] to = new int[] { R.id.label };

    if(lw.getAdapter() == null){
        adapter = new SimpleCursorAdapter(this, R.layout.todo_row, cursor, from,
                to, 0);
        Log.v("Count",Integer.toString(cursor.getCount()));
        lw.setAdapter(adapter);
    }
    else
    {
        adapter.swapCursor(cursor);
    }
}

泰的帮助

推荐答案

所以你几乎没有在回答你自己的问题使用adapter.swapCursor(光标)是正确的。

Using adapter.swapCursor(cursor) is correct so you're almost there in answering your own question.

您第一块code不起作用,因为当你的数据库更新之后调用fillData(),您只需拨打adapter.notifyDataSetChanged()和数据集实际上并没有改变,因为游标是一样的。游标是一个参考,以便从数据库行和更新底层数据库不刷新光标。你的第二件code确实刷新光标并交换了新一期的适配器(也触发更新,势必视图)。

Your first piece of code doesn't work because when you call fillData() after your database update, you simply call adapter.notifyDataSetChanged() and the dataset hasn't actually changed because the cursor is the same. A cursor is a reference to rows from your database and updating the underlying database doesn't refresh the cursor. Your second piece of code does refresh the cursor and swaps the new one in to the adapter (which also triggers an update to the view it is bound to).

更常用的方法为code这是:

The more common way to code this is:

添加此接口,以你的活动:

Add this interface to your activity:

public class MyActivity extends Activity implementsLoaderManager.LoaderCallbacks<Cursor>

在的onCreate,设置在适配器(注意该光标为空在这一点):

In onCreate, set up the adapter (note that the cursor is null at this point):

String[] from = new String[] { TodoTable.COLUMN_SUMMARY, TodoTable.COLUMN_ID};
int[] to = new int[] { R.id.label };
adapter = new SimpleCursorAdapter(this, R.layout.todo_row, null, from, to, 0);  //Note that the cursor is null
lw.setAdapter(adapter);

启动加载器:

Initiate the loader:

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

这在后台线程调用onCreateLoader(所以如果你的查询长时间运行也不会阻塞UI线程)。当它完成,onLoadFinished称为UI线程,你可以在新的光标交换的。

This calls onCreateLoader in a background thread (so if your query is long running it won't block the UI thread). When it finishes, onLoadFinished is called on the UI thread where you can swap in the new cursor.

在做了删除或更新,重新启动装载器:

After you do a delete or update, restart the loader:

getLoaderManager().restartLoader(0, null, this);

这要求onLoaderReset从而消除从适配器现有的光标,然后调用onCreateLoader又在一个新的交换。

This calls onLoaderReset which removes the existing cursor from the adapter and then calls onCreateLoader again to swap in a new one.

最后补充这些方法:

public Loader<Cursor> onCreateLoader(int id, Bundle args)
{
    String[] from = new String[] { TodoTable.COLUMN_SUMMARY, TodoTable.COLUMN_ID};
    String where = TodoTable.COLUMN_DELETED + " = ?";

    Loader<Cursor> loader = new CursorLoader(this, TodoContentProvider.CONTENT_URI, from, where, new String[] {"0"}, null);     
    return loader;
}

public void onLoadFinished(Loader<Cursor> loader, Cursor cursor)
{
    adapter.swapCursor(cursor);
}

public void onLoaderReset(Loader<Cursor> loader)
{
    adapter.swapCursor(null);
}

这篇关于数据库更新和adapter.notifyDataSetChanged()后列表视图不更新;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆