【问题标题】:Obtaining the current Android view and forcing it to be redrawn获取当前Android视图并强制重绘
【发布时间】:2012-08-11 06:05:52
【问题描述】:

当显示已更新的数据时,如何获取当前的 Android 视图并强制重绘?我通过 Android 的 Notepad tutorial 完成了第三课,没有任何问题——毕竟提供了解决方案——但我被困在我的第一次不平凡的修改上。

我在添加注释按钮旁边的菜单中添加了一个新按钮。当按下该按钮时,该按钮会在系统中每个笔记的标题中添加一个字母。但是,无论我等待多长时间,新标题都不会出现在笔记列表中。我知道更新程序可以工作,因为如果我关闭应用程序并将其重新启动,更改确实会出现。

到目前为止,我发现我必须使用某种失效方法来使程序用新值重绘自身。我知道 invalidate() 用于 UI 线程,postInvalidate() 用于非 UI 线程 1、2,但我什至不知道我在哪个线程中。另外,这两个方法都必须从需要绘图的View 对象中调用,我不知道如何获取该对象。我尝试的一切都返回null。

我的主要课程:

public boolean onMenuItemSelected(int featureId, MenuItem item) {
    switch(item.getItemId()) {
        case INSERT_ID:
            createNote();
            return true;
        case NEW_BUTTON:
            expandTitles();
            return true;
        default:
            // Intentionally empty
    }
    return super.onMenuItemSelected(featureId, item);
}

private void expandTitles() {
    View noteListView = null;

    // noteListView = findViewById(R.layout.notes_list); // null

    // noteListView =
    //   getWindow().getDecorView().findViewById(android.R.id.content);
    // From SO question 4486034

    noteListView = findViewById(R.id.body); // Fails

    mDbHelper.expandNoteTitles(noteListView);
}

我的 DAO 类:

public void expandNoteTitles(View noteListView) {
    Cursor notes = fetchAllNotes();
    for(int i = 1; i <= notes.getCount(); i++) {
        expandNoteTitle(i);
    }

    // NPE here when attempt to redraw is not commented out
    noteListView.invalidate(); // Analogous to AWT's repaint(). Not working.
    // noteListView.postInvalidate(); // Like repaint(). Not working.
}

public void expandNoteTitle(int i) {
    Cursor note = fetchNote(i);
    long rowId =
      note.getLong(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_ROWID));
    String title =
      note.getString(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)) + "W";
    String body =
      note.getString(note.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY));
    updateNote(rowId, title, body);
}

我必须做什么才能在我按下按钮后立即显示更新的笔记标题?

显然,我是 Android 的新手。我指出这一点是为了鼓励您使用小词并解释甚至是显而易见的事情。我知道这是第 100 万个“Android 不重绘”问题,但我已经阅读了数十篇现有帖子,它们要么不适用,要么对我没有意义。

1:What does postInvalidate() do?
2:What is the difference between Android's invalidate() and postInvalidate() methods?

【问题讨论】:

    标签: android android-layout invalidation


    【解决方案1】:

    根据教程,现有笔记列表显示在 ListView 中。那是一个基于适配器的视图,所以它显示的项目来自一个扩展BaseAdapter 类的适配器。在这些情况下,您应该通过调用其notifyDatasetChanged 方法来通知适配器内容已更改。这将通知 ListView 更新和重绘其行。

    编辑:

    对不起,我现在意识到这个例子使用了 CursorAdapters。这些从从数据库查询获得的 Cursor 对象中获取要显示的项目。现在,notifyDatasetChanged() 告诉适配器的是,支持适配器的数据已更改,因此基于此适配器显示内容的视图需要重绘其内容。对于 CursorAdapter,此数据来自游标。因此,您还需要重新查询该游标,从数据库中刷新它,如下所示:

    private void expandTitles() {
            mDbHelper.expandNoteTitles();
    
            CursorAdapter adapter = (CursorAdapter)getListAdapter();
            adapter.getCursor().requery();
        }
    

    在这种情况下,requery() 方法会自动调用 notifyDatasetChanged(),因此您无需担心,列表会自行更新。另请参阅此线程:https://groups.google.com/forum/?fromgroups#!topic/android-developers/_FrDcy0KC-w%5B1-25%5D。

    【讨论】:

    • 如果我理解正确,该视图基于fillData() 中看到的SimpleCursorAdapter。我删除了noteListView 并在调用SimpleCursorAdapter listAdapter = (SimpleCursorAdapter) getListAdapter(); listAdapter.notifyDataSetChanged(); 后添加了expandNoteTitles(),但应用程序的行为没有任何变化。
    • 奇怪的是,这适用于我的模拟器,但不适用于我的手机,即使它们运行相同版本的 Android。不过,我想解决这个问题是一个单独的问题。
    猜你喜欢
    • 2011-12-07
    • 1970-01-01
    • 2012-03-23
    • 1970-01-01
    • 1970-01-01
    • 2011-10-19
    • 1970-01-01
    • 1970-01-01
    • 2012-06-22
    相关资源
    最近更新 更多