0

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

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

我的代码在这里:

    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]
}  
4

1 回答 1

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);
    }
}

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

于 2013-05-17T07:05:55.293 回答