【问题标题】:Refresh a SimpleCursorAdapter after performing work on a non-UI thread在非 UI 线程上执行工作后刷新 SimpleCursorAdapter
【发布时间】:2011-02-16 06:54:49
【问题描述】:

我正在尝试从 XML 解析非 UI 线程的 ListView 中显示的 SimpleCursorAdapter 上调用 .notifyDataSetChange() ,但我终生无法弄清楚如何操作。我已经搜索了所有内容,发现的所有文章都是关于从 ListView 本身内部刷新的文章,而我没有这样做。我想不出一种方法来传递适配器或从父级获取它,或者我需要做什么才能从另一个线程调用它的方法。

ListView 将在我下次启动 Activity 时正常更新,但我希望它在 XML 解析完成后立即刷新,以便用户立即看到新数据。

答案可能很简单;它只是在逃避我。提前感谢您的帮助!

这是我的代码:

public class DirectoryListActivity extends DirectoryActivity {

public final Handler mHandler = new Handler();

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.directory_list);

    // Populate the ListView
    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
    queryBuilder.setTables(
        directoryPeople.PEOPLE_TABLE
    );

    String asColumnsToReturn[] = { 
            //snip
    };

    mCursor = queryBuilder.query(mDB, asColumnsToReturn, null, null,
            null, null, directoryPeople.DEFAULT_SORT_ORDER);

    startManagingCursor(mCursor);

// HERE'S THE ADAPTER
    SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
            R.layout.directory_people_item, mCursor,
            new String[]{
                //snip
            new int[]{
                //snip
    ); 

    ListView av = (ListView)findViewById(R.id.listPeople);
    av.setAdapter(adapter);

    //Perform sync in background
    startXMLParseThread();

}

    public void startXMLParseThread() {

    new Thread () {

        boolean success = false;

        public void run() {
            try {
                // XML-Parsing and Table-Updating code

            } catch (Exception e) {
                success = false;
            }

            mHandler.post(new Runnable() {
                public void run() {
                    TextView txtUpdateStatus = (TextView)findViewById(R.id.txtUpdateStatus);
                    if (success) {
                        txtUpdateStatus.setText(R.string.synced);
                    } else {
                        txtUpdateStatus.setText(R.string.sync_failed);
                    }
                    adapter.notifyDataSetChanged(); // ECLIPSE HATES
                }
            });
        }
    }.start();
    }
}
}

【问题讨论】:

    标签: android


    【解决方案1】:

    无需创建新适配器...

    .notifyDataSetChanged() 应仅在数据行实际更改(插入或删除行)的情况下调用,以防您刚刚更新行上的值,只需在光标上调用 requery() 就足够了:

    adapter.getCursor().requery();
    

    编辑:根据您的评论,我发现您实际上存在编译问题...

    您必须将适配器声明为类成员(在 mHandler 声明之前/之后:private SimpleCursorAdapter adapter

    然后在初始化的时候,替换

    SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
        R.layout.directory_people_item, mCursor,
        new String[]{
            //snip
            new int[]{
            //snip
    ); 
    

    与:

    adapter = new SimpleCursorAdapter(this,
        R.layout.directory_people_item, mCursor,
        new String[]{
            //snip
            new int[]{
            //snip
    ); 
    

    【讨论】:

    • 问题是我不知道如何在线程完成工作后立即访问adapter。我从 Eclipse 得到adapter cannot be resolved。这可能只是一些我不知道的关于 Threads 的简单事情,但它让我望而却步。
    • 我确实在 XML 解析过程中插入了行,所以我想我需要的不仅仅是重新查询。
    • 我更新了我的答案来解决编译问题。如果您更改行,那么 notifyDataSetChanged() 应该可以工作,如果它不尝试重新查询。
    • 我知道事情会如此简单。太感谢了!它与adapter.getCursor().requery(); 一起工作,我之前有adapter.notifyDataSetChange()(在这种情况下不起作用),并且SimpleCursorAdapter adapter 被定义为你建议的类成员。再次感谢!
    【解决方案2】:

    在查询完成后创建一个新适配器并将其设置为您的列表视图以给出一个总体思路以下是 gridview 的示例,根据您的需要进行相应更改

    globalAdapter = new GridImageAdapter(getApplicationContext());
    globalAdapter.notifyDataSetChanged();
    grid.setAdapter(globalAdapter);
    grid.invalidateViews();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-10
      相关资源
      最近更新 更多