将图像从 URL 加载到 ListView
Posted
技术标签:
【中文标题】将图像从 URL 加载到 ListView【英文标题】:Loading image from URL to ListView 【发布时间】:2017-07-13 17:20:03 【问题描述】:我正在尝试制作列表视图。我在没有从 url 加载照片的情况下成功地做到了这一点,而没有使用自定义数组适配器。但是如何在不使用自定义数组适配器的情况下实现从 url 加载图像?
我正在尝试使用来自 thread 的工作代码,但它给 holder 带来了错误。
错误部分
icon = new ImageDownloaderTask(holder.imageView).execute(doctorPhoto);
DoctorsActivity.java
public class DoctorsActivity extends AppCompatActivity
private JSONArray arrayAdapter;
private static final String URL_FOR_BALANCE = "http://192.168.1.28/api2/doctors.php";
String cancel_req_tag = "login";
private ListView lv;
ArrayList<HashMap<String, String>> contactList;
Bitmap icon = null;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_doctors);
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
getSupportActionBar().setCustomView(R.layout.toolbar_doctors);
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#003764")));
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
SharedPreferences sharedPreferences = getSharedPreferences(Config.SHARED_PREF_NAME, Context.MODE_PRIVATE);
final String pid = sharedPreferences.getString(Config.UID_SHARED_PREF, null);
contactList = new ArrayList<>();
lv = (ListView) findViewById(R.id.list);
StringRequest strReq = new StringRequest(Request.Method.POST,
URL_FOR_BALANCE, new Response.Listener<String>()
@Override
public void onResponse(String response)
try
JSONObject jObj = new JSONObject(response);
boolean error = jObj.getBoolean("error");
if (!error)
JSONArray contacts = jObj.getJSONArray("user");
for (int i = 0; i < contacts.length(); i++)
JSONObject c = contacts.getJSONObject(i);
String doctorTitle = c.getString("title");
String doctorName = c.getString("first_name");
String doctorSurname = c.getString("last_name");
String doctorPhoto = c.getString("photo"); //image URL
String doctorMobile = c.getString("mobile");
String doctorFullName = doctorTitle+" "+doctorName+" "+doctorSurname;
icon = new ImageDownloaderTask(holder.imageView).execute(doctorPhoto);
// tmp hash map for single contact
HashMap<String, String> contact = new HashMap<>();
// adding each child node to HashMap key => value
contact.put("photo", icon);
contact.put("doctor", doctorFullName);
contact.put("mobile", doctorMobile);
// adding contact to contact list
contactList.add(contact);
ListAdapter adapter = new SimpleAdapter(
DoctorsActivity.this, contactList,
R.layout.activity_doctors_list_item, new String[]"photo", "doctor",
"mobile", new int[]R.id.photo,
R.id.doctor, R.id.mobile);
lv.setAdapter(adapter);
else
String errorMsg = jObj.getString("error_msg");
Toast.makeText(getApplicationContext(),
errorMsg, Toast.LENGTH_LONG).show();
catch (JSONException e)
e.printStackTrace();
, new Response.ErrorListener()
@Override
public void onErrorResponse(VolleyError error)
Toast.makeText(getApplicationContext(),
error.getMessage(), Toast.LENGTH_LONG).show();
)
@Override
protected Map<String, String> getParams()
// Posting params to login url
Map<String, String> params = new HashMap<String, String>();
params.put("uid", pid);
params.put("lang", Locale.getDefault().getDisplayLanguage());
return params;
;
// Adding request to request queue
AppSingleton.getInstance(getApplicationContext()).addToRequestQueue(strReq,cancel_req_tag);
class ImageDownloaderTask extends AsyncTask<String, Void, Bitmap>
private final WeakReference<ImageView> imageViewReference;
public ImageDownloaderTask(ImageView imageView)
imageViewReference = new WeakReference<ImageView>(imageView);
@Override
protected Bitmap doInBackground(String... params)
return downloadBitmap(params[0]);
@Override
protected void onPostExecute(Bitmap bitmap)
if (isCancelled())
bitmap = null;
if (imageViewReference != null)
ImageView imageView = imageViewReference.get();
if (imageView != null)
if (bitmap != null)
imageView.setImageBitmap(bitmap);
else
Drawable placeholder = null;
imageView.setImageDrawable(placeholder);
private Bitmap downloadBitmap(String url)
HttpURLConnection urlConnection = null;
try
URL uri = new URL(url);
urlConnection = (HttpURLConnection) uri.openConnection();
final int responseCode = urlConnection.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK)
return null;
InputStream inputStream = urlConnection.getInputStream();
if (inputStream != null)
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
catch (Exception e)
urlConnection.disconnect();
Log.w("ImageDownloader", "Errore durante il download da " + url);
finally
if (urlConnection != null)
urlConnection.disconnect();
return null;
【问题讨论】:
【参考方案1】:为什么不使用像 https://github.com/bumptech/glide 这样的第 3 方库?
相关代码:
// ...
new Glide
.with(convertView.getContext())
.load(url)
.centerCrop()
.placeholder(R.drawable.noimage)
.crossFade()
.into(bmImage);
holder.tvName.setText(doctorList.get(position).getName());
holder.tvMobile.setText(doctorList.get(position).getMobile());
// ...
【讨论】:
【参考方案2】:对于所有想要使用带有图像的 listView 的人来说,这是我更正的工作自定义适配器:
public class DoctorAdapter extends ArrayAdapter<Doctors>
ArrayList<Doctors> doctorList;
LayoutInflater vi;
int Resource;
ViewHolder holder;
public DoctorAdapter(Context context, int resource, ArrayList<Doctors> objects)
super(context, resource, objects);
vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Resource = resource;
doctorList = objects;
@Override
public View getView(final int position, View convertView, ViewGroup parent)
View v = convertView;
if (v == null)
holder = new ViewHolder();
v = vi.inflate(Resource, null);
holder.imageview = (ImageView) v.findViewById(R.id.photo);
holder.tvName = (TextView) v.findViewById(R.id.doctor);
holder.tvMobile = (TextView) v.findViewById(R.id.mobile);
holder.callButton = (Button) v.findViewById(R.id.btnCall);
holder.callButton.setTag(holder);
holder.callButton.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
ViewHolder viewHolder = (ViewHolder) view.getTag();
String message= viewHolder.tvMobile.getText().toString();
Toast.makeText(view.getContext(), message, Toast.LENGTH_SHORT).show();
);
v.setTag(holder);
else
holder = (ViewHolder) v.getTag();
holder.imageview.setImageResource(R.drawable.noimage);
new DownloadImageTask(holder.imageview).execute(doctorList.get(position).getImage());
holder.tvName.setText(doctorList.get(position).getName());
holder.tvMobile.setText(doctorList.get(position).getMobile());
return v;
static class ViewHolder
public ImageView imageview;
public TextView tvName;
public TextView tvMobile;
public Button callButton;
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap>
ImageView bmImage;
public DownloadImageTask(ImageView bmImage)
this.bmImage = bmImage;
protected Bitmap doInBackground(String... urls)
String urldisplay = urls[0];
Bitmap mIcon = null;
try
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon = BitmapFactory.decodeStream(in);
catch (Exception e)
Log.e("Error", e.getMessage());
e.printStackTrace();
return mIcon;
protected void onPostExecute(Bitmap result)
bmImage.setImageBitmap(result);
【讨论】:
以上是关于将图像从 URL 加载到 ListView的主要内容,如果未能解决你的问题,请参考以下文章
Android - 在显示进度时将图像从 URL 加载到 ImageView(不保存图像)
如何将图像从 url 沿侧输入类型文件加载到 html5 画布?
如何将图像从 url 加载到小部件的 android 远程视图中
从 URL 加载 Compound Drawable 中的图像