2012-04-05 100 views
10

爲什麼當我打電話給notifyDatasetChanged()時,我的listview不會更新? 的唯一途徑,我可以讓它顯示的數據,再次調用setAdatper()上的ListView ...我還試圖通過runOnUIThread(),它並沒有改變任何東西BaseAdapter.notifyDatasetChanged()不更新ListView

適配器叫它

/** 
* Adapter to provide the data for the online scores 
* 
* @author soh#zolex 
* 
*/ 
public class OnlineScoresAdapter extends BaseAdapter { 

    private Context context; 
    private List<ScoreItem> scores = new ArrayList<ScoreItem>(); 

    /** 
    * Constructor 
    * 
    * @param Context context 
    */ 
    public OnlineScoresAdapter(Context context) { 

     this.context = context; 
    } 

    /** 
    * Add an item to the adapter 
    * 
    * @param item 
    */ 
    public void addItem(ScoreItem item) { 

     this.scores.add(item); 
    } 

    /** 
    * Get the number of scores 
    * 
    * @return int 
    */ 
    public int getCount() { 

     return this.scores.size(); 
    } 

    /** 
    * Get a score item 
    * 
    * @param int pos 
    * @return Object 
    */ 
    public Object getItem(int pos) { 

     return this.scores.get(pos); 
    } 

    /** 
    * Get the id of a score 
    * 
    * @param in pos 
    * @retrn long 
    */ 
    public long getItemId(int pos) { 

     return 0; 
    } 

    /** 
    * Get the type of an item view 
    * 
    * @param int pos 
    * @return int 
    */ 
    public int getItemViewType(int arg0) { 

     return arg0; 
    } 

    /** 
    * Create the view for a single list item. 
    * Load it from an xml layout. 
    * 
    * @param int pos 
    * @param View view 
    * @param ViewGroup viewGroup 
    * @return View 
    */ 
    public View getView(int pos, View view, ViewGroup group) { 

     LinearLayout layout; 
     if (view == null) { 

      layout = (LinearLayout)View.inflate(this.context, R.layout.scoreitem, null); 

     } else { 

      layout = (LinearLayout)view; 
     } 

     TextView position = (TextView)layout.findViewById(R.id.pos); 
     TextView time = (TextView)layout.findViewById(R.id.time); 
     TextView player = (TextView)layout.findViewById(R.id.player); 
     TextView createdAt = (TextView)layout.findViewById(R.id.created_at); 

     ScoreItem item = (ScoreItem)getItem(pos); 
     player.setText(item.player); 
     position.setText(String.valueOf(new Integer(item.position)) + "."); 
     time.setText(String.format("%.4f", item.time)); 
     createdAt.setText(item.created_at); 

     return layout; 
    } 

    /** 
    * Get the number of different views 
    * 
    * @return int 
    */ 
    public int getViewTypeCount() { 

     return 1; 
    } 

    /** 
    * Return wheather the items have stable IDs or not 
    * 
    * @return boolean 
    */ 
    public boolean hasStableIds() { 

     return false; 
    } 

    /** 
    * Return wheather the list is empty or not 
    * 
    * @return boolean 
    */ 
    public boolean isEmpty() { 

     return this.scores.size() == 0; 
    } 

    /** 
    * No need of a data observer 
    * 
    * @param DataSetObserver arg0 
    * @return void 
    */ 
    public void registerDataSetObserver(DataSetObserver arg0) { 

    } 

    /** 
    * No need of a data observer 
    * 
    * @param DataSetObserver arg0 
    * @return void 
    */ 
    public void unregisterDataSetObserver(DataSetObserver arg0) { 

    } 

    /** 
    * No item should be selectable 
    * 
    * @return boolean 
    */ 
    public boolean areAllItemsEnabled() { 

     return false; 
    } 

    /** 
    * No item should be selectable 
    * 
    * @param int pos 
    * @return boolean 
    */ 
    public boolean isEnabled(int arg0) { 

     return false; 
    } 
} 

的活動

的XMLLoaderThread工作正常,它只是notifyDatasetChanged似乎什麼也不做......

/** 
* Obtain and display the online scores 
* 
* @author soh#zolex 
* 
*/ 
public class OnlineScoresDetails extends ListActivity { 

    WakeLock wakeLock; 
    OnlineScoresAdapter adapter; 
    boolean isLoading = false; 
    int chunkLimit = 50; 
    int chunkOffset = 0; 

    @Override 
    /** 
    * Load the scores and initialize the pager and adapter 
    * 
    * @param Bundle savedInstanceState 
    */ 
    public void onCreate(Bundle savedInstanceState) { 

     super.onCreate(savedInstanceState); 

     PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 
     this.wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "racesow"); 

     adapter = new OnlineScoresAdapter(this); 
     setListAdapter(adapter); 
     this.loadData(); 

     setContentView(R.layout.listview); 
     getListView().setOnScrollListener(new OnScrollListener() { 

      public void onScrollStateChanged(AbsListView view, int scrollState) { 

      } 

      public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 

       if (totalItemCount > 0 && visibleItemCount > 0 && firstVisibleItem + visibleItemCount >= totalItemCount) { 

        if (!isLoading) { 

         loadData(); 
        } 
       } 
      } 
     }); 
    } 

    public void loadData() { 

     final ProgressDialog pd = new ProgressDialog(OnlineScoresDetails.this); 
     pd.setProgressStyle(ProgressDialog.STYLE_SPINNER); 
     pd.setMessage("Obtaining scores..."); 
     pd.setCancelable(false); 
     pd.show(); 

     isLoading = true; 
     String mapName = getIntent().getStringExtra("map"); 
     XMLLoaderThread t = new XMLLoaderThread("http://racesow2d.warsow-race.net/map_positions.php?name=" + mapName + "&offset=" + this.chunkOffset + "&limit=" + this.chunkLimit, new Handler() { 

      @Override 
      public void handleMessage(Message msg) { 

       switch (msg.what) { 

        // network error 
        case 0: 
         new AlertDialog.Builder(OnlineScoresDetails.this) 
          .setMessage("Could not obtain the maplist.\nCheck your network connection and try again.") 
          .setNeutralButton("OK", new OnClickListener() { 

           public void onClick(DialogInterface arg0, int arg1) { 

            finish(); 
            overridePendingTransition(0, 0); 
           } 
          }) 
          .show(); 
         break; 

        // maplist received 
        case 1: 
         pd.dismiss(); 
         InputStream xmlStream; 
         try { 

          xmlStream = new ByteArrayInputStream(msg.getData().getString("xml").getBytes("UTF-8")); 
          XMLParser parser = new XMLParser(); 
          parser.read(xmlStream); 

          NodeList positions = parser.doc.getElementsByTagName("position"); 
          int numPositions = positions.getLength(); 
          for (int i = 0; i < numPositions; i++) { 

           Element position = (Element)positions.item(i); 

           ScoreItem score = new ScoreItem(); 
           score.position = Integer.parseInt(parser.getValue(position, "no")); 
           score.player = parser.getValue(position, "player"); 
           score.time = Float.parseFloat(parser.getValue(position, "time")); 
           score.created_at = parser.getValue(position, "created_at"); 

           adapter.addItem(score); 
          } 

          adapter.notifyDataSetChanged(); 


          chunkOffset += chunkLimit; 
          isLoading = false; 

         } catch (UnsupportedEncodingException e) { 

          new AlertDialog.Builder(OnlineScoresDetails.this) 
           .setMessage("Internal error: " + e.getMessage()) 
           .setNeutralButton("OK", null) 
           .show(); 
         } 

         break; 
       } 

       pd.dismiss(); 
      } 
     }); 

     t.start(); 
    } 

    /** 
    * Acquire the wakelock on resume 
    */ 
    public void onResume() { 

     super.onResume(); 
     this.wakeLock.acquire(); 
    } 

    /** 
    * Release the wakelock when leaving the activity 
    */ 
    public void onDestroy() { 

     super.onDestroy(); 
     this.wakeLock.release(); 
    } 

    /** 
    * Disable animations when leaving the activity 
    */ 
    public void onBackPressed() { 

     this.finish(); 
     this.overridePendingTransition(0, 0); 
    } 
} 
+0

你是否開始了錯誤信息?另外,您是否在for循環之前檢查numPositions的值? – 2012-04-05 15:54:01

+0

正如我所說的,當我調用setListAdapter()而不是notifiyDataSetChanged()數據出現時...但是然後列表從頂部開始,而不是用戶滾動到的位置。所以數據在那裏,但視圖沒有更新 – 2012-04-05 16:07:07

+0

現在也嘗試了一個AsyncTask,相同的結果,沒有更新的視圖,只有當我再次調用setAdapter() – 2012-04-05 16:07:28

回答

0

您應該在每次操作數據集後調用adapter.notifyDataSetChanged()。如果你在一個批次(如for -loop)添加項目,這意味着你必須把.notifyDataSetChanged在循環,像這樣:

for(int i = 0; i < numPositions; i++) { 
    .... 
    adapter.addItem(score); 
    adapter.notifyDataSetChanged(); 
} 

確保您從UI線程調用adapter.notifyDataSetChanged()

如果你願意更新一次您的適配器,存儲您ScoreItem S IN的ArrayList和循環調用後:再次

adapter.addAll(scoreList); 
adapter.notifyDataSetChanged(); 

不過,據我所知有實在沒有理由這樣做。

+0

我也試圖在循環中調用通知,但它沒有改變任何東西。 – 2012-04-05 16:28:53

+0

看起來你不是從UI線程調用它。確保從你的UI線程調用'.notifyDataSetChanged()',例如通過使用runOnuiThread(新的Runnable(){...}); – Reinier 2012-04-05 17:00:47

+0

也不會改變任何東西 – 2012-04-14 10:42:52

1

我不確定自定義BaseAdapter的實現是否正確。

嘗試改變

public long getItemId(int pos) { 
    return 0; 
} 

public long getItemId(int pos) { 
    return pos; 
} 

我也發現了這個簡單的tutorial這可能是關於如何實現BaseAdapter很有幫助。解決此問題後,您可以再次嘗試notifyDataSetChanged()。

+0

那沒有幫助 – 2012-04-14 10:37:15

+0

這是爲我工作的。我做了一些研究,看起來沒有提供有效的itemId,BaseAdapter不會有沒有它的DataSetObserver,顯然,您的適配器不會收到數據更改的通知。 – 2015-10-21 11:40:56

5

有點晚了,但答案是,你不應該執行

public void registerDataSetObserver(DataSetObserver arg0) { 

} 

public void unregisterDataSetObserver(DataSetObserver arg0) { 

} 

我剛做了一個簡單的BaseAdapter按預期運行,誰停止添加這兩種方法後工作。我認爲「某人」需要觀察數據變化等等:)