我尝试创建ListView。它包含由单个xml-template +一个视图创建的几个自定义视图,用于指示进度。 ProgressView始终必须位于我的自定义ListView的底部。 所以,这是代码:
public class SearchActivity extends Activity implements OnXMLDataGetterComplete {
private ListView mMainLayout;
private HotelsListAdapter mHotelsListAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
mHotelsListAdapter = new HotelsListAdapter(); //create my custom adapter
mHotelsListAdapter.setLoading(true); //sets that my ListView will be show ProgressView at the bottom
mMainLayout = (ListView) findViewById(R.id.search_activity_layout);
mMainLayout.setAdapter(mHotelsListAdapter); //set adapter for my ListView
getData(); //start to receive data from web
}
//this function runs after HTTP-query
public void onGetData(final List data) { //receives list of some data
runOnUiThread(new Runnable() {
@Override
public void run() {
Iterator<XMLDataGetter.HotelListXMLParser.HotelListXMLEntry> it = data.iterator();
while (it.hasNext()) {
XMLDataGetter.HotelListXMLParser.HotelListXMLEntry item = it.next();
mHotelsListAdapter.setLoading(data.size() != 0);
HotelItemView hotel = new HotelItemView(SearchActivity.this); //create some custom view by received data
...
mHotelsListAdapter.addItem(hotel); //add this view to the adapter
}
mHotelsListAdapter.notifyDataSetChanged(); //THIS NOT WORKS
}
}
}
public class HotelsListAdapter extends BaseAdapter { //ny custom adapter
private List<HotelItemView> mItems = new ArrayList<HotelItemView>(); //list, which contains all created custom views
private boolean mIsLoading = false; //variable, which determines, whether ProgressView will be shown
private RelativeLayout mLoadingView; //layout of activity
public HotelsListAdapter() {
LayoutInflater inflater = (LayoutInflater) ((Context) SearchActivity.this).getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mLoadingView = (RelativeLayout) inflater.inflate(R.layout.hotel_list_loading, null); //inflate ProgressView
}
@Override
public boolean areAllItemsEnabled() {
return true;
}
@Override
public boolean isEnabled(int position) {
return true;
}
@Override
public void registerDataSetObserver(DataSetObserver observer) {
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
}
@Override
public int getCount() {
if (mIsLoading)
return mItems.size() + 1; //custom adapter contains children vies + ProgressView
else
return mItems.size(); //custom adapter contains only children views
}
@Override
public Object getItem(int position) {
if (position > mItems.size() - 1)
return mLoadingView; //return ProgressView
else
return mItems.get(position); //return child view
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return (View) getItem(position);
}
@Override
public int getItemViewType(int position) {
return 0;
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public boolean isEmpty() {
return false;
}
public void addItem(HotelItemView item) {
mItems.add(item);
}
public void clear() {
mItems.clear();
}
public void setLoading(boolean loading) {
mIsLoading = loading;
}
public boolean isLoading() {
return mIsLoading;
}
}
}
此示例包含ProgressBarView,但我尝试删除有关它的引用:
@Override
public int getCount() {
return mItems.size(); //custom adapter contains only children views
}
@Override
public Object getItem(int position) {
return mItems.get(position); //return child view
}
并且notifyDataSetChanged()无论如何都不起作用。我的问题是什么?我无法显示添加的视图。
我尝试在otifyDataSetChanged()之前添加mMainLayout.invalidateViews()。所以我看到了我的观看列表,但每三到五次我就得到了异常“适配器的内容已经改变,但ListView没有收到通知”。我该怎么办?
主要是我不需要清除我的适配器。添加子视图必须是增量的。我也尝试扩展ListAdapter,但它根本没有这样的方法
答案 0 :(得分:0)
也许不要覆盖适配器的registerDataSetObserver方法。
其他一些提示:
我建议您使用ArrayAdapter,如果没有理由不使用它,因为它会为您节省一些基本配置并为您处理列表管理。 此外,不要将列表中的视图保存为显示,而是保存数据的项目。 ListAdapters可以为您回收视图,因此列表中的每个项目都没有一个视图,但每个可见的项目都有一个视图。在getView方法中,如果'convertView'参数不为空,则可以重用此视图,因此只需填充其数据并将其返回即可。这将提高List的性能并大大降低内存消耗。
对于Async的东西,最好使用AsyncTask,它更好地与Android系统集成,并且可以更轻松地在后台任务之前和之后在UI线程中运行东西。
答案 1 :(得分:-1)
尝试
mHotelsListAdapter.setNotifyOnChange(true);