Android Listview 异步图像加载

标签 android listview asynchronous

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

最佳答案

嘿,按照几个步骤从服务器下载图像并显示在 ListView 中

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

这就是全部谢谢

关于Android Listview 异步图像加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26806914/

相关文章:

android - 如何更改umano滑动面板中可见区域的高度?

android - 在不过滤重复 UUID 的情况下获取 BLE 扫描

安卓 NFC : 'd' prepended on NDEF payload

java - 仅可绘制的 ListView

javascript - JavaScript Promise 中 return 的用法

Android 包含布局

c# - WPF - 打印 ListView 的内容?

C# 从 ListView 外部的控件中删除 ListView 中的项目

c# - .NET Reactive Framework 的良好介绍

.net - 在字节模式和异步中重用 NamedPipeServerStream 的正确方法