在 ListView 的自定义适配器中从 URL 加载图像(Android Studio)

Posted

技术标签:

【中文标题】在 ListView 的自定义适配器中从 URL 加载图像(Android Studio)【英文标题】:Loading image from URL in custom adapter for ListView (Android Studio) 【发布时间】:2015-07-09 09:27:21 【问题描述】:

虽然位图似乎被正确提取,但变量“userBitmap”将保持为空。但是,当在我的平板电脑上向上或向下滚动时,新的列表行将包含图片,但它们都是相同且错误的。真的,真的很迷茫。我尝试了许多不同的方法从网络上获取图像。非常感谢任何帮助。

我的自定义适配器:

public class MessagesArrayAdapter extends ArrayAdapter<ChatData>

    Bitmap userBitmap;

public MessageArrayAdapter(Context context, List<ChatData> objects)

    super(context, 0, objects);


public View getView(int position, View convertView, ViewGroup parent)

    ChatCell chatCell = new ChatCell();

    LayoutInflater inflater = LayoutInflater.from(getContext());
    convertView = inflater.inflate(R.layout.cell_chat, parent, false);

    chatCell.usernameTextView = (TextView) convertView.findViewById(R.id.usernameTextView);
    chatCell.messageTextView = (TextView) convertView.findViewById(R.id.messageTextView);
    chatCell.userImageView = (ImageView) convertView.findViewById(R.id.userImageView);

    ChatData chatData = getItem(position);

    // Get user image from web
    new loadImageAsync().execute(chatData.avatarURL);

    chatCell.userImageView.setImageBitmap(userBitmap);
    chatCell.usernameTextView.setText(chatData.username);
    chatCell.messageTextView.setText(chatData.message);

    return convertView;




private static class ChatCell

    TextView usernameTextView;
    TextView messageTextView;
    ImageView userImageView;


private class loadImageAsync extends AsyncTask<String, Void, Double>
    @Override
    protected Double doInBackground(String... params) 

        userBitmap = loadImage(params[0]);


        return null;
    



public Bitmap loadImage(String str) 

    InputStream instream = null;
    try 
        HttpGet httpRequest = new HttpGet(URI.create(str));
        HttpClient httpclient = new DefaultHttpClient();
        HttpResponse response = (HttpResponse) httpclient.execute(httpRequest);
        HttpEntity entity = response.getEntity();
        BufferedHttpEntity bufHttpEntity = new BufferedHttpEntity(entity);
        instream = bufHttpEntity.getContent();
        Bitmap myBitmap = BitmapFactory.decodeStream(instream);

        return myBitmap;
     catch (Exception e) 
        e.printStackTrace();
        return null;
     finally 
        //close input
        if (instream != null) 
            try 
                instream.close();
             catch (IOException ioex) 
                // Handle error
            
        
    


【问题讨论】:

我会使用Picasso,过上幸福的生活。 【参考方案1】:

解决问题的最简单方法是使用一些库,例如 Picasso。它不仅更易于使用并使您的代码更易于阅读,而且还可以防止您在图像太大时出现 OutOfMemory 异常。加载图像只需一行:

Picasso.with(context)
.load(urlOfYourImage)
.resize(50, 50) // here you resize your image to whatever width and height you like
.into(imageView)

【讨论】:

天哪。这是给我的。 希望这会有所帮助。只是简化。 ;) 一切都在一行代码中运行。不敢相信。你认为我还应该使用异步吗? 将这行代码添加到 build.gradle 中的依赖项中: compile 'com.squareup.picasso:picasso:2.5.2'【参考方案2】:

我认为您在这里遇到了两个问题:

1) 视图回收 - 我自己是 android 新手,在使用列表视图时经常出现这种情况,当部分列表视图移出屏幕时,它们在向后滚动时可能会出错。我个人在上下滚动时遇到了按钮状态更改为错误行的问题。 This tutorial 更详细地介绍了回收是什么,并在对我有用的 View Holder 私有类中提供了一个解决方案。我相信 SO 的其他部分也会讨论这个问题。

2) Image Null - 这肯定是 null,还是只是没有出现在列表视图中?如果是前者,则 LoadImage() 中的某些步骤一定不能正常工作。如果是后者,您可能想在设置图像后尝试调用 notifyDataSetChanged(),以告诉主线程图像已准备好绘制。如下所示(在您的 AsyncTask 中):

@Override
protected void onPostExecute() 
       notifyDataSetChanged();
    

【讨论】:

感谢您的评论。 notifyDataSetChange();帮助。现在,所有的视图都有图片。但是,它们都是相同的,并且每秒都在变化(而文本视图保持不变/正确)。我认为这与在 getView() 之外定义的“userBitmap”有关。有没有更好的方法来做到这一点?

以上是关于在 ListView 的自定义适配器中从 URL 加载图像(Android Studio)的主要内容,如果未能解决你的问题,请参考以下文章

片段中 ListView 的自定义适配器不起作用

Android ListView 和带有 ViewHolder 的自定义适配器

具有包含 CheckBoxes 的自定义适配器的 Listview

带有过滤器 Android 的自定义 Listview 适配器

如何在 listview onClick() 中从 POJO 获取项目?

ArrayIndexOutOfBoundsException 与 ListView 中的多个视图的自定义 Android 适配器