异步设置listview中的图像

时间:2013-05-16 00:26:18

标签: android image android-listview android-asynctask repeat

我在listview中设置图片时遇到问题。 所有图像都被加载,但是它们不是逐个设置的,例如,当加载一个图像时,它将被加载到列表中的所有视图中,而不仅仅是在所需的位置。

图像比我更好,但我没有足够的声誉。

我的代码在这里:

    public class Sightsee{
private String sightseeName;
private String sightseeInfo;
private double sightseeLatitude;
private double sightseeLongitude;
private String sightseeImageUri;
private String sightseeCity;
private double sightseeDistance;
private static Bitmap image;
private SightseeAdapter ssa;
private DownloadableBitmap downloadableBitmap; 

public Sightsee( String sightseeName, String sightseeInfo,double d,double e, String sightseeImageUri,String sightseeCity,double sightseeDistance){
    this.sightseeName =sightseeName;
    this.sightseeInfo =sightseeInfo;
    this.sightseeLatitude = d;
    this.sightseeLongitude=e;
    this.sightseeCity=sightseeCity;
    this.sightseeDistance=sightseeDistance;
    this.sightseeImageUri=sightseeImageUri;
    this.downloadableBitmap = new DownloadableBitmap();
    this.downloadableBitmap.setImageUri(sightseeImageUri);
    this.image=null;
}

public Bitmap getImage(){
    return image;
}

public void setImage(Bitmap bm){
    this.image=bm;
}

public SightseeAdapter getAdapter(){
    return ssa;
}
public void setAdapter(SightseeAdapter ssa){
     this.ssa=ssa;
}

public void loadImage(SightseeAdapter ssa){
    this.ssa=ssa;
    if(sightseeImageUri!=null ){
        new ImageLoadTask().execute(sightseeImageUri);
    }
}
public String getSightseeName() {
    return sightseeName;
}

public void setsightseeName(String sightseeName) {
    this.sightseeName = sightseeName;
}
public String getSightseeInfo() {
    return sightseeInfo;
}
public void setsightseeInfo(String sightseeInfo) {
    this.sightseeInfo = sightseeInfo;
}
public double getSightseeLatitude() {
    return sightseeLatitude;
}
public void setsightseeLatitude(double sightseeLatitude) {
    this.sightseeLatitude = sightseeLatitude;
}
public double getSightseeLongitude() {
    return sightseeLongitude;
}
public void setsightseeLongitude(double sightseeLongitude) {
    this.sightseeLongitude = sightseeLongitude;
}
public DownloadableBitmap getDownloadableBitmap() {
    return downloadableBitmap;
}
public void setDownloadableBitmap(DownloadableBitmap downloadableBitmap) {
    this.downloadableBitmap = downloadableBitmap;
}   

public String getSightseeCity() {
    return sightseeCity;
}
public void setsightseeCity(String sightseeCity) {
    this.sightseeCity = sightseeCity;
}

public double getSightseeDistance() {
    return sightseeDistance;
}
public void setSightseeDistance(double sightseeDistance) {
    this.sightseeDistance = sightseeDistance;
}

public String getPictureLocation(){
    return sightseeImageUri;
}

public void setsightseePictureLocation(String sightseeImageUri) {
    this.sightseeImageUri = sightseeImageUri;
}


// ASYNC TASK TO AVOID CHOKING UP UI THREAD
private class ImageLoadTask extends AsyncTask<String, String, Bitmap> {



    // PARAM[0] IS IMG URL
    protected Bitmap doInBackground(String... param) {
         CommonFunctions.infoLog("ImageLoadTask", "Attempting to load image URL: " + param[0]);

         Bitmap b = ImageDownloader.downloadImage(param[0]);

         return b;
    }

    protected void onProgressUpdate(String... progress) {
        // NO OP
    }

    protected void onPostExecute(Bitmap ret) {
        if (ret != null) {
             CommonFunctions.infoLog("ImageLoadTask", "Successfully loaded image");
            image = ret;

            if (ssa != null) {
                // WHEN IMAGE IS LOADED NOTIFY THE ADAPTER

              ssa.notifyDataSetChanged();
            }
        } else {

            CommonFunctions.infoLog("ImageLoadTask", "Failed to load ");
        }
    }
}


}


   private class SightseeLoaderTask extends AsyncTask<String, Void, ArrayList<Sightsee>>{

    ProgressDialog dialog;
    public SightseeLoaderTask(){
        dialog = new ProgressDialog(DiscoverAround.this);
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        dialog.setMessage(getResources().getString(R.string.ProgressBar_Loading_Message));
        dialog.setCancelable(true);
        dialog.setOnCancelListener(new OnCancelListener()
        {
            @Override
            public void onCancel(DialogInterface dialog)
            {
                SightseeLoaderTask.this.cancel(true);
            }
        });
        dialog.show();
    }

    @Override
    protected ArrayList<Sightsee> doInBackground(String... params) {
        ArrayList<Sightsee> SightseeList = new ArrayList<Sightsee>();

        if(CommonFunctions.isConnectedToInternet(DiscoverAround.this)){
        try {
            String ret = getUrlString(params[0]);
            ret = ret.trim();           
            JSONObject jsonObj = new JSONObject(ret);
            CommonFunctions.infoLog("jObj",jsonObj.toString());
            int success = jsonObj.getInt("success");
            if(success == 1){

            JSONArray Sightsees = jsonObj.getJSONArray("Location");
            JSONObject tmp;
            for(int i=0; i<Sightsees.length(); i++){
                tmp = Sightsees.getJSONObject(i);
                Sightsee _Sightsee = new Sightsee(
                        tmp.getString("locationName"), 
                        tmp.getString("locationInfo"), 
                        tmp.getDouble("locationLatitude"), 
                        tmp.getDouble("locationLongitude"),
                        tmp.getString("locationPic"),
                        tmp.getString("city"),
                        tmp.getDouble("distance")
                        );
                SightseeList.add(_Sightsee);
            } 


          }     

        } catch (SocketTimeoutException e) {
            //CommonFunctions.getAlertDialog(DiscoverAround.this, Constants.ALERTDIALOG_TYPE_SOCKET_TIMEOUT_ERROR, "", Constants.ALERTDIALOG_BUTTON_CLICKMODE_DISMISS).show();
            CommonFunctions.exceptionLog(e);
            return null;

        } catch (MalformedURLException e) {
            CommonFunctions.getAlertDialog(DiscoverAround.this, Constants.ALERTDIALOG_TYPE_SERVER_ERROR, "", Constants.ALERTDIALOG_BUTTON_CLICKMODE_DISMISS).show();
            CommonFunctions.exceptionLog(e);
            return null;

        } catch (IOException e) {
            CommonFunctions.getAlertDialog(DiscoverAround.this, Constants.ALERTDIALOG_TYPE_SERVER_ERROR, "", Constants.ALERTDIALOG_BUTTON_CLICKMODE_DISMISS).show();
            CommonFunctions.exceptionLog(e);
            return null;

        } catch (JSONException e) {
            //CommonFunctions.getAlertDialog(DiscoverAround.this, Constants.ALERTDIALOG_TYPE_SERVER_ERROR, "", Constants.ALERTDIALOG_BUTTON_CLICKMODE_DISMISS).show();
            CommonFunctions.exceptionLog(e);  //json exception
            return null;


        } 
    }
        else {
            CommonFunctions.getAlertDialog(DiscoverAround.this, Constants.ALERTDIALOG_TYPE_CONNECTIONERROR, "", Constants.ALERTDIALOG_BUTTON_CLICKMODE_DISMISS).show();
        }
        return SightseeList;
    }

    @Override
    protected void onPostExecute( ArrayList<Sightsee>result) {
        super.onPostExecute(result);
        if(dialog != null && dialog.isShowing()) {
            dialog.dismiss();   
        if( result!=null ){
        SightseeList = (ListView) findViewById(R.id.list);


//asdfglllhf
        adapter = new SightseeAdapter(DiscoverAround.this, result);

        // SET AS CURRENT LIST
        SightseeList.setAdapter(adapter); 


        int i=0;
      for (Sightsee s : result) {
                // START LOADING IMAGES FOR EACH ITEM

            s.loadImage(adapter); 
        } 

//asdfglllhf


        }
        else {
            CommonFunctions.infoLog("sightseeList","empty");
            CommonFunctions.getAlertDialog(DiscoverAround.this, Constants.ALERTDIALOG_TYPE_NOTFOUND_ERROR, "", Constants.ALERTDIALOG_BUTTON_CLICKMODE_DISMISS).show();

        }
    }
}
}
 static class ViewHolder {

        ImageView image;
        TextView name;
        TextView distance;
        Button btn;
        int pos;
    }



public class SightseeAdapter extends BaseAdapter{

     private LayoutInflater mInflater;
    private ArrayList<Sightsee> objectsList;
    public SightseeAdapter(Context context,
            ArrayList<Sightsee> objects) {


        this.objectsList=objects;


    }
    public int getCount() {
        return objectsList.size();
    }

    public Sightsee getItem(int position){
        return objectsList.get(position);
    }

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

    private Sightsee Sightsee;


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    // Sightsee s =objectsList.get(position);
    Sightsee =objectsList.get(position);
   ViewHolder holder;
    // ViewHolder holder = new ViewHolder();
     LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    // SightseeImage = (ImageView) convertView.findViewById(R.id.place_image);
     View row = convertView;
        if (row == null) {
            row = vi.inflate(R.layout.customcomponent_list, null);

            holder=new ViewHolder();

           holder.image = (ImageView) row.findViewById(R.id.place_image);

            row.setTag(holder);
            //SightseeImage = (ImageView) convertView.findViewById(R.id.place_image);
        } else {
             holder=(ViewHolder) row.getTag();

        }
           if (Sightsee.getImage() != null) {
               holder.image.setImageBitmap(Sightsee.getImage());


           } else {
                    // MY DEFAULT IMAGE
                    holder.image.setImageResource(R.drawable.arrow);
            }


        Sightsee = getItem(position);   

      holder.name = (TextView) row.findViewById(R.id.place_name);
      holder.distance = (TextView)row.findViewById(R.id.place_distance);
      convertView.findViewById(R.id.show_button);



        holder.name.setText(Sightsee.getSightseeName());

        double value = Sightsee.getSightseeDistance();

        holder.distance.setText( String.valueOf((float) (long) (value * 100) / 100.0) +" km");

    ![enter image description here][2]
}  

1 个答案:

答案 0 :(得分:0)

您可以将ImageView发送到任务构造函数,并在那里保留对图像路径的引用。现在在onPostExecute中,检查ImageView的当前标记是否与您开始使用的标记相同。如果是,则设置图像。如果不是,请不要做任何事情。

但是,这意味着无论如何都会下载图像。你不会在视图上设置错误的图像。

编辑:首先将ImageView传递给任务构造函数:

new LoadImage(imageView).execute()

然后在LoadImage构造函数中保存对ImageView和图像路径的引用。在构造函数中而不是在doInBackground中保存路径非常重要,以确保我们不会遇到多线程问题。然后在onPostExecute我们检查当前路径。

class LoadImage extends AsyncTask<Object, Void, Bitmap>{

        private ImageView imv;
        private String path;

        public LoadImage(ImageView imv) {
             this.imv = imv;
             this.path = imv.getTag().toString();
        }

    @Override
    protected Bitmap doInBackground(Object... params) {
        Bitmap bitmap = null;
        File file = new File( 
                Environment.getExternalStorageDirectory().getAbsolutePath() + path);

        if(file.exists()){
            bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
        }

        return bitmap;
    }
    @Override
    protected void onPostExecute(Bitmap result) {
        if (!imv.getTag().toString().equals(path)) {
               /* The path is not same. This means that this
                  image view is handled by some other async task. 
                  We don't do anything and return. */
               return;
        }

        if(result != null && imv != null){
            imv.setVisibility(View.VISIBLE);
            imv.setImageBitmap(result);
        }else{
            imv.setVisibility(View.GONE);
        }
    }

}

您可能会遇到错误放置图像的问题,因此您可以使用以下解决方案。

 @Override
protected void onPostExecute(Bitmap result) {

    if (!imv.getTag().toString().equals(rec_id)) {
           return;
    }

    if(result != null && imv != null){
        int index = id.indexOf(imv.getTag().toString());
        if(list.getFirstVisiblePosition()<=index && index<=list.getLastVisiblePosition())
        {
            imv.setVisibility(View.VISIBLE);
            imv.setImageBitmap(result);
        }
    }else{
        imv.setImageBitmap(icon);
        imv.setVisibility(View.GONE);
    }
}

此处列表是listview的对象。只需将列表视图对象传递给适配器并粘贴此函数,而不是onPostExecute函数。