Android Listview异步图像加载

时间:2014-11-07 17:37:35

标签: android listview asynchronous

我有listview,我正在尝试实现异步任务,将图像加载到我的适配器的getView方法内的视图中。我已经成功创建了这个,但是我的问题是,因为在listview和适配器中视图被回收,用户滚动列表视图的时间很短,位于布局中的imageView显示视图的图像以前的位置。然后它显示正确的图像。我已经尝试在调用异步任务之前将getView方法中的imageView位图设置为null但它的行为仍然相同。如何在图像加载完成之前使用异步任务将图像加载到视图中而不显示先前的图像?

3 个答案:

答案 0 :(得分:1)

嘿,按照几步从服务器下载图像并在列表视图中显示

步骤1.在项目中创建此类

OnImageDownloaded.java

public class OnImageDownloaded {

public OnImageDownloaded() {
    try {
        if (Environment.getExternalStorageState().equals(
                Environment.MEDIA_MOUNTED)) {
            File file = new File(Environment.getExternalStorageDirectory()
                    .getAbsolutePath() + File.separator + "your_Dir_name");
            if (file.mkdirs()) {
            }
        } else {
            Log.e("testing", "External Directory is not mounted");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public void downloadTheImages(ArrayList<String> imageUrls) {
    try {
        new downloadingTheImages(imageUrls).execute();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

class downloadingTheImages extends AsyncTask<Void, Void, Void> {
    ArrayList<String> imageUrls;

    public downloadingTheImages(ArrayList<String> imageUrls) {
        this.imageUrls = imageUrls;
    }

    @Override
    protected Void doInBackground(Void... params) {
        try {
            for (int i = 0; i < imageUrls.size(); i++) {
                if (imageUrls.get(i).equals("0")) {
                } else
                    downloadTheImageIfRequired(imageUrls.get(i));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

public void downloadTheImageIfRequired(String imageName) {
    try {
        String dirPath = Environment.getExternalStorageDirectory()
                .getAbsolutePath()
                + File.separator
                + "your_Dir_name"
                + File.separator;
        String CompleteFilePath = dirPath + imageName;
        File f = new File(CompleteFilePath);
        if (f.exists()) {
        } else {
            URL url = new URL(
                    "http image URL ::"
                            + imageName);
            URLConnection conexion = url.openConnection();
            conexion.connect();

            InputStream input = new BufferedInputStream(url.openStream());
            OutputStream output = new FileOutputStream(CompleteFilePath);
            byte data[] = new byte[1024];
            int count;
            while ((count = input.read(data)) != -1) {
                output.write(data, 0, count);
            }
            output.flush();
            output.close();
            input.close();
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

}

第2步。

查看你如何获得该图像

  private class getImage extends AsyncTask<Void, Void, String> {
    Dialog dialog;
    String url;

    @Override
    protected void onPreExecute() {
        super.onPreExecute();

    }

    @Override
    protected String doInBackground(Void... params) {
        url = getResources().getString(R.string.baseurl) + "getNews";

        JSONParser jParser = new JSONParser();
        String json = jParser.getJSONFromUrl(url);
        try {
            JSONObject jobject = new JSONObject(json);
            Log.e("testing", "url: " + url + " " + json);
            int success = jobject.getInt("success");
            Log.e("testing", "json length" + jobject.length());
            for (int i = 0; i < jobject.length() - 1; i++) {
                JSONObject jobj = jobject
                        .getJSONObject(Integer.toString(i));
                if (success == 1) {
                    HashMap<String, String> hm = new HashMap<String, String>();
                    ArrayList<String> tempAl1 = new ArrayList<String>();

                    tempAl1.add(jobj.getString("image"));
                    if (tempAl1.size() > 0) {
                        new OnImageDownloaded().downloadTheImages(tempAl1);
                    }

                    Log.e("test", "image" + jobj.getString("image"));

                    hm.put(image, jobj.getString("image"));

                    aldata.add(hm);
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        if (dialog != null)
            if (dialog.isShowing())
                dialog.dismiss();
         Custom_Adapter adapter = new Custom_Adapter (
                (Activity) context, aldata);
        lv.setAdapter(adapter);
    }
}

第3步。

在适配器中显示该图像

在adaper中的getview中调用这些方法

   @Override
   public View getView(int position, View convertView, ViewGroup parent) {
    View view = convertView;
    view = null;
    if (view == null) {
        LayoutInflater inflator = context.getLayoutInflater();
        view = inflator.inflate(R.layout.news_view, null);
        final ViewHolder viewHolder = new ViewHolder();
        initAll(view, viewHolder);
        view.setTag(viewHolder);
    }
    ViewHolder holder = (ViewHolder) view.getTag();
    fillAll(holder, position);
    return view;

}

 public void fillAll(final ViewHolder holder, final int position) {

    String dirPath = Environment.getExternalStorageDirectory()
            .getAbsolutePath()
            + File.separator
            + "your_Dir_name"
            + File.separator;
    String CompleteFilePath = dirPath + allData.get(position).get("image");
    File f = new File(CompleteFilePath);
    if (f.exists()) {
        Log.e("testingTag", "if part");
        holder.ivimage.setVisibility(View.VISIBLE);
        catchOutOfMemory(holder.ivimage, CompleteFilePath);
    } else {
        Log.e("testingTag", "else part");
        holder.ivimage.setVisibility(View.GONE);
    }

    Log.e("test", "image" + allData.get(position).get("image"));



}

void catchOutOfMemory(ImageView iv, String path) {
    try {
        iv.setImageURI(Uri.parse(path));
    } catch (OutOfMemoryError e) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 8;
        Bitmap preview_bitmap = BitmapFactory.decodeFile(path, options);
        iv.setImageBitmap(preview_bitmap);
    }
}
非常感谢

答案 1 :(得分:1)

我遇到了同样的问题,然后我开始使用Square&#39; Picasso,它非常简单,完美地处理了imageview回收!

答案 2 :(得分:0)

在适配器中,您需要使用ViewHolder(以有效地回收视图)并设置标记(在视图上)以将视图绑定到正确的图像。您已经知道getView(...)回调中的位置。