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 - setOnPreferenceClickListener 函数不适用于 Android 上的 Preference

android - 谷歌分析是否提供应用程序下载 API?

android - minSdkVersion 9 不能小于库中声明的版本 14

java - 单击时 ListView 选择多个项目

ios - findObjectsInBackgroundWithBlock : gets data from Parse, 但数据只存在于 block 内

java - 从 SD 卡读取文件的标准方法

android - setOnItemClickListener 事件不起作用

android - 多列列表中的 nullPointerException

java - 异步 Java ReSTLet Web 服务的示例?

c# - 您可以使用 Task.Run 将受 CPU 限制的工作移至后台线程