【问题标题】:Display default image in imageview if no image returned from server如果服务器没有返回图像,则在 imageview 中显示默认图像
【发布时间】:2020-03-01 09:06:41
【问题描述】:

目标

当没有从服务器下载图像时显示默认图像。

问题

我有一个带有图像视图的列表视图(以及一些文本框,但这并不重要)。 我的 imageview 为学生下载图像,但是当学生没有图像时,我试图显示默认图像。 我已经尝试了两件我认为应该可行的事情,设置默认图像或下面的代码。 此代码取自一个活动文件,我将数据库列中的值写入变量(仅显示 img 以保持简单性)

                   //Image path returned
                    if (javaRealObject.getString("img").equals(""))
                    {
                        imgv = (ImageView)findViewById(R.id.ivImage);
                        imgv.setImageResource(R.drawable.emptyhead);

                        Log.d("Test", "Empty");
                    }
                    else//No image found in column
                    {
                        student.setImage(javaRealObject.getString("img"));
                        Log.d("Test","Not Empty");
                    }  

但是我在imgv = (ImageView)findViewById(R.id.ivImage); 上得到了一个空引用,我不知道为什么,因为我的图像视图被声明了。 当没有默认图像时,任何帮助都可以实现默认图像的效果 从列提供将不胜感激。

对于更多的上下文,上面的代码是一个调用 listview.xml 的活动,然后调用 row.xml。有问题的图像视图在 row.xml 文件中。

ROW.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="4dp"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <ImageView
            android:id="@+id/ivImage"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="8dp"
            android:src="@drawable/empty_head" /> //default image here

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/tvFirstName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="@color/primary"
                android:textAppearance="?android:attr/textAppearanceLarge" />
            </LinearLayout>
    </LinearLayout>
</LinearLayout>

调用行的列表

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="450dp"
        tools:listitem="@layout/row" >
    </ListView>
</LinearLayout>

适配器:

public class DriverAdapter extends ArrayAdapter<Drivers> {

    ArrayList<Drivers> ArrayListDrivers;
    int Resource;
    Context context;
    LayoutInflater vi;

    public DriverAdapter(Context context, int resource, ArrayList<Drivers> objects) {
        super(context, resource, objects);

        ArrayListDrivers = objects;
        Resource = resource;
        this.context = context;

        vi = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder holder;
        if (convertView == null) {
            convertView = vi.inflate(Resource, null);
            holder = new ViewHolder();

            holder.imageview = (ImageView) convertView.findViewById(R.id.ivImage);
            holder.tvName = (TextView) convertView.findViewById(R.id.tvFirstName);
            holder.tvDescription = (TextView) convertView.findViewById(R.id.tvLastName);
            holder.tvClientid = (TextView) convertView.findViewById(R.id.tvid);
            holder.tvExpires = (TextView) convertView.findViewById(R.id.tv_expdate);

            convertView.setTag(holder);

        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.imageview.setImageResource(R.drawable.ic_launcher);
            new DownloadImageTask(holder.imageview).execute(ArrayListDrivers.get(position).getImage());


        Glide.with(holder.imageview.getContext())
                .load(new DownloadImageTask(holder.imageview).execute(ArrayListDrivers.get(position).getImage())        )
                .centerCrop()
                .placeholder(R.drawable.ic_launcher)
                .crossFade()
                .into(holder.imageview);


        holder.tvName.setText(ArrayListDrivers.get(position).getFirstname());
        holder.tvDescription.setText(ArrayListDrivers.get(position).getLastname());
        holder.tvClientid.setText(ArrayListDrivers.get(position).getClient_id());
        holder.tvExpires.setText("Expiry Date:"+ArrayListDrivers.get(position).getExpires());



        return convertView;


    }

    static class ViewHolder {
        public ImageView imageview;
        public TextView tvName;
        public TextView tvDescription;
        public TextView tvClientid;
        public TextView tvExpires;

    }


    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 cImg1 = null;


            try {

                byte[] decodedString = Base64.decode(urldisplay, Base64.DEFAULT);
                cImg1 = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);


            } catch (Exception e) {
                Log.e("Error", e.getMessage());
                e.printStackTrace();
            }
            return cImg1;


        }

        protected void onPostExecute(Bitmap result) {

            bmImage.setImageBitmap(result);


        }
    }
}

【问题讨论】:

  • 请发布您的 XML 代码。
  • 上面的代码来自你的适配器类..?
  • 发布 xml 并记录。如果其他条件,您还必须声明上面的 findViewbyId 行。
  • @Tanimreja 这不是适配器类,它是 doinbackground 方法中代码的一部分,该方法从数据库中的列中获取的值分配字符串。
  • 哦,您已经在 Async 内部初始化了 imageView,这就是它给您 NullPointer 的原因。在 Async 之外初始化 ImageView

标签: android


【解决方案1】:

有一种更好的方法可以做到这一点,您可以使用以下图像加载库之一:

Glide.

一个专注于平滑滚动的 Android 图像加载和缓存库

您只需一行代码即可完成您想做的事情。

    Glide.with(myFragment)
    .load(url)
    .placeholder(R.drawable.loading_spinner)
    .into(myImageView);

它更简单、更干净。

【讨论】:

  • 我实际上想使用它,但我有一个问题。我已经编辑了问题并添加了我的适配器。您能否提供有关在那里实施 Glide 的进一步说明?
  • 我收到无法解析方法占位符的错误。你有什么想法为什么会这样吗?当然,Glide 库已添加到项目中。
  • 您可以用代码提出新问题,我可以帮助您。但您的占位符名称可能有错别字
  • 我和毕加索用的一样
【解决方案2】:

我通过做一些非常简单的事情解决了这个问题。 在我简单说的 aync 方法的 post execute 中。

  if (result != null){
                bmImage.setImageBitmap(result);
            }

这样如果为null,默认的imageview不会被“null”覆盖 . 感谢指导

【讨论】:

    【解决方案3】:

    Listview 的适配器负责管理行的视图。 你的适配器是什么样的? (您调用 listview.setAdapter(Adapter) 的对象)。

    在您的适配器内部,有一个方法调用 getView 您需要覆盖并返回一个视图对象。您需要在此视图对象上调用 view.findviewbyId(),而不是在您的活动上

    更新 尝试删除这些行

    holder.imageview.setImageResource(R.drawable.ic_launcher);
            new DownloadImageTask(holder.imageview).execute(ArrayListDrivers.get(position).getImage());
    

    P/s 你能解释一下调用 Glide.with(Context).load(object) 的目的吗?谢谢

    【讨论】:

    • 请看我的适配器代码。我在里面设置了图片资源
    【解决方案4】:

    此方法可行 - 在您的 xml 代码中设置默认图像,当学生没有图像时将显示该图像。 如果您有图像,则使用 setImageResource(...) 动态设置图像。

    重新检查您的 ImageView 的 ID,因为您收到空引用错误,如果这不能解决问题,请发布完整的活动代码。

    【讨论】:

    • 是的,您将收到空引用错误,因为您的活动不知道您的 row.xml,您只能在包含列表视图的 xml 中调用视图。您只能在您在列表视图中设置该行的地方访问该图像视图,就像在适配器类中一样
    • 我在我的适配器中正是这样做的(我在上面粘贴了它)但是没有显示默认图像。我相信这是因为它分配给它“nohnig”,因为它从查询中的图像路径中什么也得不到。
    【解决方案5】:

    在您的AsyncTask constructor 中尝试像这样初始化您的图像视图

    LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View convertView = inflater.inflate(R.layout.row, null, false);
    ivImage= (ImageView ) convertView.findViewById(R.id.ivImage);
    

    在这里row.xml 声明 ImageView ...并确保 ivImage 是全局变量...现在 ivImage 不为空。我检查了它.. 但最好使用adapter 类来管理listview row....

    【讨论】:

    • 我试过 inflater = (LayoutInflater) getApplicationContext().getSystemService(context.LAYOUT_INFLATER_SERVICE); (在 onCreate 中)和 View convertView = inflater.inflate(R.layout.row, null, false); ivImage= (ImageView) convertView.findViewById(R.id.ivImage); imgv.setImageResource(R.drawable.empty_head);在 Aync 方法中但仍然没有默认图像
    【解决方案6】:

    添加gradle依赖:

       implementation 'com.github.bumptech.glide:glide:4.11.0'
       implementation 'jp.wasabeef:glide-transformations:4.0.0'
    

    为了使用它:

      Glide.with(mActivity.getApplicationContext())
                                .load(EndPoints.ROWS_IMAGE_URL + ImageUrl)
                                .asBitmap()
                                .centerCrop()
                                .transform(new CropCircleTransformation(mActivity.getApplicationContext()))
                                .apply(new RequestOptions().
                                .placeholder(drawable)
                                .error(drawable)
                                .override(AppConstants.ROWS_IMAGE_SIZE, AppConstants.ROWS_IMAGE_SIZE))
                                .into(target);
    

    以下代码行会导致在发生错误时显示默认图像:

       .placeholder(drawable)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-23
      • 1970-01-01
      • 1970-01-01
      • 2023-02-05
      • 2022-01-08
      • 2021-01-12
      • 2013-05-27
      • 1970-01-01
      相关资源
      最近更新 更多