为什么在调用notifyDatasetChanged()时我的listview没有更新? 我可以让它显示数据的唯一方法是再次调用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);
}
}
答案 0 :(得分:6)
有点晚但答案是你不应该实施
public void registerDataSetObserver(DataSetObserver arg0) {
}
public void unregisterDataSetObserver(DataSetObserver arg0) {
}
我只是有一个简单的BaseAdapter
按预期工作,在添加这两种方法后停止工作。我认为“某人”需要观察数据变化,例如:)
答案 1 :(得分:1)
我不确定您的Custom BaseAdapter的实现是否正确。
尝试更改
public long getItemId(int pos) {
return 0;
}
到
public long getItemId(int pos) {
return pos;
}
我还发现这个简单的tutorial可能对如何实现BaseAdapter有所帮助。完成此操作后,您可以再次尝试notifyDataSetChanged()。
答案 2 :(得分:0)
每次操作数据集后都应该调用adapter.notifyDataSetChanged()
。如果您要批量添加项目(例如for
- 循环),这意味着您必须在循环中放置.notifyDataSetChanged,如下所示:
for(int i = 0; i < numPositions; i++) {
....
adapter.addItem(score);
adapter.notifyDataSetChanged();
}
确保从您的UI主题中调用adapter.notifyDataSetChanged()
。
如果您要更新适配器一次,请将ScoreItem
存储在ArrayList
和循环调用之后:
adapter.addAll(scoreList);
adapter.notifyDataSetChanged();
但话又说回来,据我所知,没有理由这样做。
答案 3 :(得分:0)
也许对某人会有帮助。为了使该方法正常工作,应确保满足以下条件:
1) getCount()
应该返回正确的项目尺寸,例如
@Override
public int getCount() {
return allMonthDays.size();
}
2) getItemId(int position)
应该返回不同的ID (如果更改了项目),因此仅返回此处的位置可能不够,例如
@Override
public long getItemId(int position) {
return allMonthDays.get(position).getTimestamp();
}
3) getView(int position, View convertView, ViewGroup parent)
应该返回所需的View
,如果要重复使用旧的{{1 }}