Android-ListView图像在滚动时被洗牌
我正在尝试使用动态加载的图像创建ListView,使用AsyncTask下载图像,然后将其设置到ListView中。我的问题是,当向下滚动时,图像会被随机更改Android-ListView图像在滚动时被洗牌,android,image,listview,android-listview,Android,Image,Listview,Android Listview,我正在尝试使用动态加载的图像创建ListView,使用AsyncTask下载图像,然后将其设置到ListView中。我的问题是,当向下滚动时,图像会被随机更改 public class GetAllCustomerListViewAdapter extends BaseAdapter { private JSONArray dataArray; private Activity activity; private static LayoutInflater inflater = null;
public class GetAllCustomerListViewAdapter extends BaseAdapter {
private JSONArray dataArray;
private Activity activity;
private static LayoutInflater inflater = null;
private static final String baseUrlForImage = "http://192.168.254.1/contact/images/";
public GetAllCustomerListViewAdapter(JSONArray jsonArray, Activity a)
{
this.dataArray = jsonArray;
this.activity = a;
inflater = (LayoutInflater) this.activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return this.dataArray.length();
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// set up convert view if it is null
final ListCell cell;
if (convertView == null)
{
convertView = inflater.inflate(R.layout.get_all_customer_list_view_cell, null);
cell = new ListCell();
cell.FullName = (TextView) convertView.findViewById(R.id.customer_full_name);
cell.Age = (TextView) convertView.findViewById(R.id.customer_age);
cell.mobile = (ImageView) convertView.findViewById(R.id.customer_mobile);
convertView.setTag(cell);
}
else
{
cell = (ListCell) convertView.getTag();
}
// change the data of cell
try
{
JSONObject jsonObject = this.dataArray.getJSONObject(position);
cell.FullName.setText(jsonObject.getString("FirstName")+" "+jsonObject.getString("LastName"));
cell.Age.setText(" "+jsonObject.getInt("Age"));
String nameOfImage = jsonObject.getString("id");
String urlForImageInServer = "http://192.168.254.1/contact/getImage.php?id="+nameOfImage;
new AsyncTask<String, Void, Bitmap>() {
@Override
protected Bitmap doInBackground(String... params) {
String url = params[0];
Bitmap icon = null;
try {
InputStream in = new java.net.URL(url).openStream();
icon = BitmapFactory.decodeStream(in);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return icon;
}
protected void onPostExecute(Bitmap result) {
cell.mobile.setImageBitmap(result);
}
}.execute(urlForImageInServer);
}
catch (JSONException e)
{
e.printStackTrace();
}
return convertView;
}
private class ListCell
{
private TextView FullName;
private TextView Age;
private ImageView mobile;
}
公共类GetAllCustomerListViewAdapter扩展BaseAdapter{
私有JSONArray数据阵列;
私人活动;
专用静态充气机=空;
私有静态最终字符串baseUrlForImage=”http://192.168.254.1/contact/images/";
公共GetAllCustomerListViewAdapter(JSONArray JSONArray,活动a)
{
this.dataArray=jsonArray;
本活动=a;
充气器=(LayoutFlater)this.activity.getSystemService(Context.LAYOUT\u充气器\u服务);
}
@凌驾
public int getCount(){
返回此.dataArray.length();
}
@凌驾
公共对象getItem(int位置){
返回位置;
}
@凌驾
公共长getItemId(int位置){
返回位置;
}
@凌驾
公共视图getView(int位置、视图转换视图、视图组父视图){
//设置转换视图(如果为空)
最终列表细胞;
if(convertView==null)
{
convertView=充气机。充气(R.layout.get\u all\u customer\u list\u view\u cell,空);
cell=新的ListCell();
cell.FullName=(TextView)convertView.findViewById(R.id.customer\u full\u name);
cell.Age=(TextView)convertView.findViewById(R.id.customer\u Age);
cell.mobile=(ImageView)convertView.findViewById(R.id.customer\u mobile);
convertView.setTag(单元格);
}
其他的
{
cell=(ListCell)convertView.getTag();
}
//更改单元格的数据
尝试
{
JSONObject JSONObject=this.dataArray.getJSONObject(位置);
cell.FullName.setText(jsonObject.getString(“FirstName”)+“”+jsonObject.getString(“LastName”);
cell.Age.setText(“+jsonObject.getInt”(“Age”);
字符串nameOfImage=jsonObject.getString(“id”);
字符串urlForImageInServer=”http://192.168.254.1/contact/getImage.php?id=“+图像名称;
新建异步任务(){
@凌驾
受保护位图doInBackground(字符串…参数){
字符串url=params[0];
位图图标=空;
试一试{
InputStream in=new java.net.URL(URL.openStream();
icon=BitmapFactory.decodeStream(in);
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
返回图标;
}
受保护的void onPostExecute(位图结果){
cell.mobile.setImageBitmap(结果);
}
}.execute(urlForImageInServer);
}
捕获(JSONException e)
{
e、 printStackTrace();
}
返回视图;
}
私有类列表单元
{
私有文本视图全名;
私人文本浏览年龄;
私用ImageView手机;
}
}我最近才这么做(实际上是凌晨1点)——问题是ListView正在积极地回收视图。因此,它会得到仍然保存位图的旧视图
以下是您需要的:
[注意:检查位图是否已提前缓存。如果未缓存,请执行以下步骤]
ImageView.setImageBitmap(null);
)公共类GetAllCustomerListViewAdapter扩展BaseAdapter{
私有JSONArray数据阵列;
私人活动;
专用静态充气机=空;
私有静态最终字符串baseUrlForImage=”http://192.168.254.1/contact/images/";
//该列表按行的顺序缓存位图和目标图像视图
私有ArrayList rowViewDataList;
公共GetAllCustomerListViewAdapter(JSONArray JSONArray,活动a)
{
this.dataArray=jsonArray;
本活动=a;
充气器=(LayoutFlater)this.activity.getSystemService(Context.LAYOUT\u充气器\u服务);
//初始化列表
rowViewDataList=newArrayList(dataArray.length());
//这更像是一个首选项,但是为rowViewDataList添加每个项目
对于(int i=0;ipublic class GetAllCustomerListViewAdapter extends BaseAdapter {
private JSONArray dataArray;
private Activity activity;
private static LayoutInflater inflater = null;
private static final String baseUrlForImage = "http://192.168.254.1/contact/images/";
// The list caches bitmaps as well as target imageViews, in order of the rows
private ArrayList<RowViewData> rowViewDataList;
public GetAllCustomerListViewAdapter(JSONArray jsonArray, Activity a)
{
this.dataArray = jsonArray;
this.activity = a;
inflater = (LayoutInflater) this.activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Initialize the list
rowViewDataList = new ArrayList<RowViewData>(dataArray.length());
// This is more of a preference, but add in every item for the rowViewDataList
for(int i = 0; i < dataArray.length(); ++i) {
// Create a new, empty rowViewData instance and put it into the list
RowViewData rowData = new RowViewData();
rowViewDataList.add(rowData);
}
}
@Override
public int getCount() {
return this.dataArray.length();
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// set up convert view if it is null
final ListCell cell;
if (convertView == null)
{
convertView = inflater.inflate(R.layout.get_all_customer_list_view_cell, null);
cell = new ListCell();
cell.FullName = (TextView) convertView.findViewById(R.id.customer_full_name);
cell.Age = (TextView) convertView.findViewById(R.id.customer_age);
cell.mobile = (ImageView) convertView.findViewById(R.id.customer_mobile);
convertView.setTag(cell);
}
else
{
cell = (ListCell) convertView.getTag();
}
// change the data of cell
try
{
JSONObject jsonObject = this.dataArray.getJSONObject(position);
cell.FullName.setText(jsonObject.getString("FirstName")+" "+jsonObject.getString("LastName"));
cell.Age.setText(" "+jsonObject.getInt("Age"));
// Get the rowViewData for this position
RowViewData curRowViewData = rowViewDataList.get(position);
// If the bitmap is already cached, just use it
if(curRowViewData.bitmap != null) {
cell.mobile.setImageBitmap(curRowViewData.bitmap);
}
// Otherwise, gotta do some real work
else {
// First, set the cell's imageView's bitmap to null
// [in case this is a recycled view already with a bitmap]
cell.mobile.setImageBitmap(null);
// Then, start up the caching system
String nameOfImage = jsonObject.getString("id");
String urlForImageInServer = "http://192.168.254.1/contact/getImage.php?id="+nameOfImage;
// Create a system to load images lazily and then receive the bitmaps
// Look at my ImageLoaderNoCache for an example. Feel free to reuse it
/**
* this = this adapter should implement an interface. Look below for the corresponding method
* url = image source url
* position = position this bitmap belongs to. Will get returned along with bitmap for reference
*/
LazyImageLoader.GetBitmap(this, url, position);
// Cache/target this imageView for later
curRowViewData.targetImageView = cell.mobile;
// Double check this imageView is not being targeted already elsewhere
// ie, one of the recycling fixes [else, two bitmaps would load at once, etc]
// Also, probably could be more efficient
for(int i = 0; i < rowViewDataList.size(); ++i) {
// If this is the current position, then skip all the logic for this round
if(i == position) continue;
// Get the rowViewData for this round
// Yeah... I should've used "cell" instead of row for you...
RowViewData checkRowData = rowViewDataList.get(i);
// If the targeted ImageView is the same, null-ify it
if(checkRowData.targetImageView == curRowViewData.targetImageView) {
// The old one should be null as the bitmap should not load suddenly into
// the current recycled item
checkRowData.targetImageView = null;
// Personally, I knew that there would only be one copy at any time
// so I tried to save time by breaking out here. Feel free to be
// cautious and comment out the break statement
break;
}
}
}
}
catch (JSONException e)
{
e.printStackTrace();
}
return convertView;
}
/**
* Should be called as part of an interface with the LazyImageLoader
* @param bitmap - The lazily loaded bitmap that was requested earlier
* @param position - The row/cell position that the bitmap was requested for
*/
public void getBitmapForPosition(Bitmap bitmap, int position) {
// Get the rowViewData instance for this row/position
RowViewData curRowData = rowViewDataList.get(position);
// Cache the bitmap
curRowData.bitmap = bitmap;
// Check if the bitmap should be loaded still
if(curRowData.targetImageView != null) {
curRowData.targetImageView.setImageBitmap(bitmap);
// Not sure if strictly necessary, but good practice to make the cached view null now
curRowData.targetImageView = null;
}
}
private class ListCell
{
private TextView FullName;
private TextView Age;
private ImageView mobile;
}
// Holds all the data for lazily loading an image with a bitmap
private class RowViewData {
public ImageView targetImageView;
public Bitmap bitmap;
}
}