BaseAdapter.notifyDatasetChanged()不更新ListView

为什么当我调用notifyDatasetChanged()时,我的列表视图不会更新? 唯一的方法,我可以让它显示数据是,再次调用ListView的setAdatper()…我也试图调用它通过runOnUIThread()这并没有改变任何东西

适配器

/** * 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); } } 

Solutions Collecting From Web of "BaseAdapter.notifyDatasetChanged()不更新ListView"

有点晚,但答案是你不应该执行

 public void registerDataSetObserver(DataSetObserver arg0) { } public void unregisterDataSetObserver(DataSetObserver arg0) { } 

我只是有一个简单的BaseAdapter按预期工作,在添加这两个方法后停止工作。 我认为“某人”需要观察数据的变化等:)

我不确定您的自定义BaseAdapter的实现是否正确。

尝试改变

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

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

我还发现这个简单的教程 ,可能会有助于如何实现BaseAdapter。 解决这个问题后,您可以再次尝试notifyDataSetChanged()。

每次操作数据集后,都应该调用adapter.notifyDataSetChanged() 。 如果你正在批量添加项目(例如for -loop),这意味着你必须把.notifyDataSetChanged放到你的循环中,像这样:

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

确保从UI线程调用adapter.notifyDataSetChanged()

如果您只更新一次适配器,请将您的ScoreItem存储在ArrayList并在循环调用之后:

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

但是,就我所知,真的没有理由这么做。