Niana
Niana

Reputation: 1047

Display default image in imageview if no image returned from server

Goal

Display a default image when no image is downloaded from server.

Problem

I have a listview with an imageview(along with a few textbox but thats not important). My imageview downloads images for students but when the student has no image I am trying to display a default image. I have tried two things I thought should work, set a default image, or the code below. This code is taken from an activity file where I write the values from the database columns to variables (only showed img to maintain simplicity)

                   //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");
                    }  

However I am getting a null refernce on imgv = (ImageView)findViewById(R.id.ivImage); and I am not sure why since my image view is being declared. Any help ti acheive the effect of a default image when none is supplied from the column will be appreciated.

For a bit more context, the code above is an activity that calls the listview.xml, which then calls the row.xml. the imageview in question is in row.xml file.

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>

List that calls row

<?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>

Adapter:

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);


        }
    }
}

Upvotes: 17

Views: 52030

Answers (6)

younes
younes

Reputation: 832

Add gradle dependency:

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

In order to use it:

  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);

The following line of code causes a default image to be displayed in the event of an error:

   .placeholder(drawable)

Upvotes: 2

Tin Tran
Tin Tran

Reputation: 2285

Your Listview's adapter is responsible for managing your rows' views. What is your adapter looks like? (the object that you call listview.setAdapter(Adapter) on).

Inside your adapter, there is a method call getView that you need to override and return a view object. You need to call view.findviewbyId() on this view object, not on your activity

UPDATE Try remove these lines

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

P/s can you explain the purpose of calling Glide.with(Context).load(object)? thank you

Upvotes: 2

Niana
Niana

Reputation: 1047

I solved this by doing something very simple. In post exeucte of the aync method I simply said.

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

That way if it is null, the default imageview will not be over written with "null" . Thanks for the guidance

Upvotes: 2

Tanim reja
Tanim reja

Reputation: 2188

In your AsyncTask constructor try to initialize your Image view like this

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);

here row.xml where you declare ImageView ... and make sure ivImage is global variable... now ivImage is not null. i checked it.. but its better to use adapter class for managing a listview row....

Upvotes: 1

humazed
humazed

Reputation: 76942

There is a better way to do that, you can use one of the image loading libs like:

Glide.

An image loading and caching library for Android focused on smooth scrolling

and it will take you just one line to do what you want.

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

it's easier and cleaner.

Upvotes: 23

Khwaja Moiz
Khwaja Moiz

Reputation: 89

This method would work - Set a default image in your xml code, which will be displayed when student has no image. Dynamically set image using setImageResource(...) if you got an image.

Recheck the id of your ImageView as you are getting null reference error and if this does not solve the problem then please post the complete activity code.

Upvotes: 1

Related Questions