将数据动态地更新ListView中,搞了两个小时,终于搞定了,感谢 txlong_onz,文章地址:http://txlong-onz.iteye.com/blog/947620。
以下代码是怎么实现动态更新ListView的方法。
package com.photographic.ui;
import java.util.List;
import com.photographic.adapter.PhotographicStudioListViewAdapter;
import com.photographic.bean.PhotographicStudioListItemBean;
import com.photographic.control.CityListDialog;
import com.photographic.service.WebServiceData;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.AbsListView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
public class PhotographicStudioList extends Activity implements AbsListView.OnScrollListener{
public static final String TAG = "PhotographicList";
private WebServiceData wsd;
public ListView listView;
public TextView photoStudioName;
private PhotographicStudioListViewAdapter adapter;
private LinearLayout loadingLayout;
private Thread loadWebDataThread;
public List<PhotographicStudioListItemBean> itemInfoList;
private List<PhotographicStudioListItemBean> itemInfoListTemp;
// private boolean refreshable;
/**
* 设置布局显示属性
*/
private LayoutParams mLayoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
/**
* 设置布局显示目标最大化属性
*/
private LayoutParams FFlayoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT);
private ProgressBar progressBar;
private static int network_error = 0;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pslist_ui);
initProgressBarPosition();
Button button = (Button)findViewById(R.id.button01);
button.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
if (network_error == 1)
{
Toast.makeText(PhotographicStudioList.this, "无法切换城市,原因是获取不到网络上的数据!", Toast.LENGTH_SHORT).show();
}
else
{
new CityListDialog(PhotographicStudioList.this).showCityListDialog();
}
}
});
// 获取ListView对象
listView = (ListView)findViewById(R.id.listview_01);
// 初始化时加载广东省广州市的影楼
wsd = new WebServiceData();
try
{
itemInfoList = wsd.getPhotoStudioListInformation(getCityId(), 1);
adapter = new PhotographicStudioListViewAdapter(this, itemInfoList);
}
catch (Exception e1)
{
network_error = 1;
Toast.makeText(this, "加载网络数据失败", Toast.LENGTH_SHORT).show();
return;
}
listView.addFooterView(loadingLayout); // 添加到脚页显示
photoStudioName = (TextView)findViewById(R.id.textview_01);
photoStudioName.setText("广州市影楼列表");
listView.setAdapter(adapter); // 给ListView添加适配器
listView.setOnScrollListener(this);
listView.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3)
{
Log.i(TAG, "success");
// 通过影楼列表的PhotoStudioID属性获得该公司的简介
Intent intent = new Intent(PhotographicStudioList.this, PhotographicStudioAbout.class);
startActivity(intent);
}
});
}
/**
* 初始化进度条
*/
private void initProgressBarPosition() {
// TODO Auto-generated method stub
// 线性布局
LinearLayout layout = new LinearLayout(this);
// 设置布局 水平方向
layout.setOrientation(LinearLayout.HORIZONTAL);
// 进度条
progressBar = new ProgressBar(this);
// 进度条显示位置
progressBar.setPadding(250, 15, 15, 15);
// 把进度条加入到layout中
layout.addView(progressBar, mLayoutParams);
// 文本内容
TextView textView = new TextView(this);
textView.setText("加载中...");
textView.setGravity(Gravity.CENTER_VERTICAL);
// 把文本加入到layout中
layout.addView(textView, FFlayoutParams);
// 设置layout的重力方向,即对齐方式是
layout.setGravity(Gravity.CENTER);
// 设置ListView的页脚layout
loadingLayout = new LinearLayout(this);
loadingLayout.addView(layout, mLayoutParams);
loadingLayout.setGravity(Gravity.CENTER);
}
/**
* 滑动状态改变时调用
*/
public void onScrollStateChanged(AbsListView view, int scrollState)
{}
/**
* 滑动时被调用
*/
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount)
{
Log.i(TAG, firstVisibleItem + visibleItemCount + "=" + totalItemCount);
if (firstVisibleItem + visibleItemCount == totalItemCount)
{
// 开线程去下载网络数据
if (loadWebDataThread == null || !loadWebDataThread.isAlive())
{
loadWebDataThread = new Thread()
{
@Override
public void run()
{
// Log.i(TAG, "enter");
// Log.i(TAG, getCityId() + "");
// Log.i(TAG, "" + bean.getTotalNumber());
int totalNum = wsd.getNumber(getCityId(), 1) + 1;
if (adapter.getCount() <= totalNum + 1)
{
int count = adapter.getCount() + 6;
int currentPage = count / 6;
// Log.i(TAG, "currentPage=" + currentPage);
try
{
itemInfoListTemp = wsd.getPhotoStudioListInformation(getCityId(), currentPage);
}
catch (Exception e)
{
e.printStackTrace();
}
}
else
{
listView.removeFooterView(loadingLayout);
}
try
{
// 这里是网络数据请求的方法,在这里用线程休眠5秒方法来处理
Thread.sleep(5000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
};
loadWebDataThread.start();
}
}
}
private Handler handler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
switch (msg.what)
{
case 1:
if (itemInfoListTemp != null)
{
itemInfoList.addAll(itemInfoListTemp);
adapter.notifyDataSetChanged();
itemInfoListTemp = null;
}
break;
default:
break;
}
}
};
/**
* 获得城市Id,默认为293
* @return
*/
private int getCityId()
{
int cityId = CityListDialog.cityId;
if (cityId == 0)
{
return 293;
}
return cityId;
}
}
-----------------------------------------------------------------------------
package com.photographic.adapter;
import java.util.List;
import com.photographic.bean.PhotographicStudioListItemBean;
import com.photographic.ui.R;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
/**
* 为影楼列表界面里的ListView自定义适配器
* @author Treasure
*
*/
public class PhotographicStudioListViewAdapter extends BaseAdapter
{
public static final String TAG = "PhotographicStudioListViewAdapter";
public List<PhotographicStudioListItemBean> itemListData;
public Activity context;
public LayoutInflater inflater;
/**
* 带参数的构造方法
* @param context 上下文
* @param itemListData 放置列表里面的数据项
*/
public PhotographicStudioListViewAdapter(Activity context,
List<PhotographicStudioListItemBean> itemListData)
{
super();
this.context = context;
this.itemListData = itemListData;
this.inflater = (LayoutInflater)context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount()
{
return itemListData.size();
}
public Object getItem(int position)
{
return itemListData.get(position);
}
public long getItemId(int position)
{
return 0;
}
public View getView(int position, View convertView, ViewGroup parent)
{
WidgetInListView widget;
if (convertView == null)
{
// 初始化ListView里面的widget
widget = new WidgetInListView();
// 用资源布局填充ListView控件
convertView = inflater.inflate(R.layout.listview_content, null);
// widget.logoImg = (ImageView)convertView.findViewById(R.id.imageview_01);
widget.photoStudioNameTxt = (TextView)convertView.findViewById(R.id.textview_02);
widget.telephoneTxt = (TextView)convertView.findViewById(R.id.textview_03);
widget.addressTxt = (TextView)convertView.findViewById(R.id.textview_04);
widget.themePhotoCountTxt = (TextView)convertView.findViewById(R.id.textview_05);
widget.priceSetCountTxt = (TextView)convertView.findViewById(R.id.textview_06);
convertView.setTag(widget);
}
else
{
widget = (WidgetInListView)convertView.getTag();
}
// 向ListView里添加数据
PhotographicStudioListItemBean itemBean = (PhotographicStudioListItemBean) itemListData
.get(position);
// widget.logoImg.setImageBitmap(itemBean.getLogo());
widget.photoStudioNameTxt.setText(showSubString(itemBean.getPhotoStudioName(), 1));
widget.telephoneTxt.setText(showSubString(itemBean.getTelephone(), 2));
widget.addressTxt.setText(showSubString(itemBean.getAddress(), 3));
widget.themePhotoCountTxt.setText("样片" + itemBean.getThemePhoto());
widget.priceSetCountTxt.setText("套系" + itemBean.getPriceSet());
return convertView;
}
/**
* 内部类,将该类里面的控件加入到ListView中
* @author Treasure
*/
private class WidgetInListView
{
// ImageView logoImg;
TextView photoStudioNameTxt;
TextView telephoneTxt;
TextView addressTxt;
TextView themePhotoCountTxt;
TextView priceSetCountTxt;
}
/**
* 为了使影楼列表界面排版友好,所以对于很长的字符串进行截取
* @param itemBean
* @param select
* @return
*/
private String showSubString(String data, int select)
{
String str = null;
switch (select)
{
case 1:
// 影楼名 汉字12个
str = cutString(data, 24);
break;
case 2:
// 电话号码 数字12个
str = cutString(data, 13);
break;
case 3:
// 地址 汉字17个
str = cutString(data, 34);
break;
}
return str;
}
/**
* 汉字
* 数字
* @param data
* @return
*/
// private int exactLength(String data)
// {
// int length = 0;
// for (int i = 0; i < data.length(); i++)
// {
// if (data.charAt(i) > 255)
// {
// length += 2;
// }
// else
// {
// length += 1;
// }
// }
// Log.i(TAG, length + "");
// return length;
// }
/**
* 截取合适的长度
* @param data
* @param num
* @return
*/
private String cutString(String data, int num)
{
int len = data.length(); // 原始数据的长度
StringBuffer sb = new StringBuffer();
int length = 0; // 累加长度,不能大于传入的值
// String[] str = new String[len]; // 创建字符串数组,用于存放传入数据的值。
for (int i = 0; i < len; i++)
{
if (length > num)
{
return sb.append("...").toString();
}
else
{
char ch = data.charAt(i);
if (ch > 255)
{
length += 2;
sb.append(ch);
}
else
{
length += 1;
sb.append(ch);
}
}
}
return sb.toString();
}
}
-----------------------------------------------------------------------------
package com.photographic.bean;
import android.graphics.Bitmap;
/**
* 影楼列表界面中的 ListView 控件里面的 get(),set() 方法
* @author Treasure
*/
public class PhotographicStudioListItemBean
{
// private Bitmap logo;
private String photoStudioName;
private String telephone;
private String address;
private String themePhoto;
private String priceSet;
// public Bitmap getLogo()
// {
// return logo;
// }
//
// public void setLogo(Bitmap logo)
// {
// this.logo = logo;
// }
public String getPhotoStudioName()
{
return photoStudioName;
}
public void setPhotoStudioName(String photoStudioName)
{
this.photoStudioName = photoStudioName;
}
public String getTelephone()
{
return telephone;
}
public void setTelephone(String telephone)
{
this.telephone = telephone;
}
public String getAddress()
{
return address;
}
public void setAddress(String address)
{
this.address = address;
}
public String getThemePhoto()
{
return themePhoto;
}
public void setThemePhoto(String themePhoto)
{
this.themePhoto = themePhoto;
}
public String getPriceSet()
{
return priceSet;
}
public void setPriceSet(String priceSet)
{
this.priceSet = priceSet;
}
}
解决的思路是:定义两个List<PhotographicStudioListItemBean>,一个用于“存放所有的数据”,一个用于“存放动态加载的数据”。对于notifyDataSetChanged()方法的理解是,只对“存放所有数据”的List<PhotographicStudioListItemBean>生效。因为它创建了自定义适配器的对象,并将“存放所有数据”的List<PhotographicStudioListItemBean>加入到适配器中。对于为什么给其它的List<PhotographicStudioListItemBean>,并创建了自定义适配器对象不管用。这个问题我无法解答,但是,大概的原理我懂。只可意会不可言传。