当显示已更新的数据并强制重绘时,如何获取当前的Android视图?我通过Android的Notepad tutorial工作并完成了第三课,没有任何问题 - 毕竟提供了解决方案 - 但我仍然坚持第一次非平凡的修改。
我在菜单中添加了一个新按钮,位于添加记事按钮旁边。按下时,该按钮会在系统中的每个音符的标题上添加一个字母。但是,无论我等多久,新标题都不会出现在笔记列表中。我知道更新程序有效,因为如果我关闭应用程序并将其重新启动,则会出现 do 更改。
到目前为止,我发现我必须使用某种失效方法来使程序重新绘制新值。我知道在UI线程中使用了invalidate()
,而在非UI线程 1,2 中使用了postInvalidate()
,但我甚至不知道我是哪个线程另外,这两个方法都必须从需要绘图的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?
答案 0 :(得分:1)
根据教程,现有笔记列表显示在ListView中。这是一个基于适配器的View,因此它显示的项目来自扩展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。