2012-08-11 62 views
2

如何在顯示已更新的數據並獲得重繪時獲取當前的Android視圖?我工作通過Android的Notepad tutorial,並完成第三課沒有任何問題—解決方案提供,畢竟—,但我堅持我的第一個不平凡的修改。獲取當前的Android視圖並強制重繪它

我在菜單上新增了一個按鈕,旁邊的添加備註按鈕。按下時,該按鈕會爲系統中每個音符的標題添加一個字母。但是,無論我等待多久,新的標題都不會顯示在音符清單中。我知道更新程序的工作原理,因爲如果我解散應用程序並將其重新啓動,則會出現做的更改

到目前爲止,我發現我必須使用某種無效方法來使程序重新繪製新值。我知道從UI線程中使用invalidate(),而從非UI線程使用postInvalidate()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的新手。我指出這一點,以鼓勵你使用小詞,並解釋甚至是明顯的事情。我知道這是第一百萬個「Android不重新繪製」的問題,但我已經閱讀了幾十個現有帖子,他們要麼不適用,要麼對我沒有意義。

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

回答

1

根據教程,現有筆記的列表在ListView呈現。這是基於適配器的視圖,所以它顯示的項目來源於延伸BaseAdapter類的適配器。在這些情況下,您應通過調用notifyDatasetChanged方法通知適配器內容已更改。這將通知ListView更新並重新繪製其行。

編輯:

對不起,我現在認識到這個示例使用CursorAdapters。這些源項目是通過從數據庫查詢中獲得的Cursor對象顯示的。現在,notifyDatasetChanged()告訴適配器的是,支持適配器的數據已更改,因此基於此適配器顯示內容的視圖需要重新繪製其內容。對於CursorAdapter,這些數據來自遊標。所以,你還需要重新查詢該遊標,從數據庫刷新,就像這樣:

private void expandTitles() { 
     mDbHelper.expandNoteTitles(); 

     CursorAdapter adapter = (CursorAdapter)getListAdapter(); 
     adapter.getCursor().requery(); 
    } 

重新查詢()方法會自動調用notifyDatasetChanged()在這種情況下,所以你不必擔心,該列表將自行更新。請參閱此主題:https://groups.google.com/forum/?fromgroups#!topic/android-developers/_FrDcy0KC-w%5B1-25%5D

+0

如果我理解正確,視圖基於'fillData()'中看到的'SimpleCursorAdapter'。我刪除了'noteListView'並添加了'SimpleCursorAdapter listAdapter =(SimpleCursorAdapter)getListAdapter(); listAdapter.notifyDataSetChanged();'調用'expandNoteTitles()'後,但沒有看到應用程序的行爲發生變化。 – Pops 2012-08-11 07:06:28

+0

奇怪的是,儘管它們運行的​​是相同版本的Android,但它適用於我的模擬器,但不適用於我的手機。不過,我認爲解決這個問題是一個單獨的問題。 – Pops 2012-08-11 16:02:03