将图像从 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 中的图像

如何从从json获得的url加载图像到collectionview

如何从 SwiftUI 中的 Bundle 中的有效路径或 URL 将图像加载到 Image()?