Philip van der Merwe
Philip van der Merwe

Reputation: 23

Downloaded Images in Listview first row shuffle through all images before correctly displaying android

I have a issue that I just seem not able to solve. Do not know if this was asked before, I might have missed it.

Overview: I am currently working as an intern android developer at a company (android experience +/- 3months). I was given a test project to do for me to learn android. The test project is about a news site/app that you get articles from JSON and when clicking on an article, you get the full article in another fragment. While in the Full article you can save the article as a favourite (store in a sqlite DB). Another fragment gets the favourites from the database and displays it in a listview that has 1 imageview, 3 textviews and 1 imagebutton.

Problem: When I get to the Favourites Fragment (displaying it):

  1. If there is only 1 row, the image displays correctly, no shuffling occurs.
  2. When there is more that 1 row in the listview, the image of the first row cycle through the images of all the rows before correctly assign/populate the images to their respective rows/articles. It takes about 1-2 seconds for the cycling of images.

Here follows my listview layout xml, the fragment layout xml and my class file.

Listview Layout xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="1dp"
android:descendantFocusability="blocksDescendants" >

<ImageView
    android:id="@+id/iv_thumb"
    android:layout_width="65dp"
    android:layout_height="65dp"
    android:layout_centerVertical="true"
    android:padding="10dp"
    android:contentDescription="@string/str_iv_thumb" />

<TextView
    android:id="@+id/tv_article_title"
    android:layout_width="250dp"
    android:layout_height="wrap_content"
    android:textSize="15sp"
    android:textStyle="bold"
    android:layout_marginTop="8dp"
    android:layout_centerHorizontal="true"
    android:layout_toRightOf="@id/iv_thumb" />

<TextView
    android:id="@+id/tv_article_date"
    android:layout_width="250dp"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_toRightOf="@id/iv_thumb"
    android:layout_below="@id/tv_article_title" />

<TextView
    android:id="@+id/tv_article_synopsis"
    android:layout_width="250dp"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_toRightOf="@id/iv_thumb"
    android:layout_below="@id/tv_article_date" />

<ImageButton
    style="@style/Rem_Fav" 
    android:id="@+id/iv_rem_favs_single"
    android:src="@drawable/remove_favourite" 
    android:layout_width="25dp"
    android:layout_height="25dp"
    android:clickable="true"
    android:layout_marginTop="8dp"
    android:layout_marginRight="5dp"
    android:layout_alignParentRight="true"
    android:layout_centerVertical="true"
    android:contentDescription="@string/rem_favs_single"
    android:layout_toRightOf="@+id/tv_article_synopsis" />

Fragment Layout xml:

<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<RelativeLayout
    android:id="@+id/relativeLayout1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    style="@style/background"  >

        <ImageView
            android:id="@+id/iv_logo"
            android:contentDescription="@string/content"
            android:layout_width="250dp"
            android:layout_height="36dp"
            android:layout_centerHorizontal="true"
            android:src="@drawable/logo" />

        <ImageButton
            style="@style/Rem_Fav" 
            android:id="@+id/iv_rem_favs"
            android:src="@drawable/remove_favourite" 
            android:clickable="true"
            android:layout_width="25dp"
            android:layout_marginRight="1dp"
            android:layout_marginTop="10dp"
            android:layout_alignParentRight="true"
            android:contentDescription="@string/rem_favs"
            android:layout_toRightOf="@id/iv_logo" />

</RelativeLayout>

<RelativeLayout
    android:id="@+id/relativeLayout2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:layout_below="@id/relativeLayout1"
    style="@style/background"  >

        <ListView
            android:id="@+id/lv_Entities"
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:clickable="true"
            tools:context=".MainActivity" />

</RelativeLayout>
</LinearLayout>

Class File:

package com.example.***;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;

import com.example.***.sqlite.SqliteController;
import com.example.***.R;

import android.annotation.SuppressLint;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.TextView;

public class FavouritesFragment extends Fragment {

// Listview attribute
ListView mListView;

List<HashMap<String, String>> articles = null;

SqliteController controller;
SQLiteDatabase db;

ImageButton allRemoveBtn;

CustomListAdapter adapter;

public FavouritesFragment() {

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    controller = new SqliteController(getActivity());
    db = controller.getWritableDatabase();

    View rootView = inflater.inflate(R.layout.fragment_favourites, container, false);

    // Setting the Title of the List
    getActivity().getActionBar().setTitle("Favourites");

    // Getting the articles from the DB
    articles = controller.getAllArticles();

    // Getting a reference to ListView of activity_main
    mListView = (ListView) rootView.findViewById(R.id.lv_Entities);

    adapter = new CustomListAdapter(getActivity(), R.layout.lv_fav_layout);

    mListView.setAdapter(adapter);

    // Log.d("LISTVIEW","mListView: " + mListView);

    /** 
     *  This section is for the Remove All from Favourites function
     *  with a pop-up window asking if the user is sure about his/her
     *  choice. If the yes button is clicked, all of the saved favourites
     *  is deleted and the image chaged to selected image.
    */

    if (articles.isEmpty()) {
        // Do not show the Delete all image button
        allRemoveBtn = (ImageButton) rootView.findViewById(R.id.iv_rem_favs);
        allRemoveBtn.setVisibility(View.INVISIBLE);
    }
    else 
    {
        allRemoveBtn = (ImageButton) rootView.findViewById(R.id.iv_rem_favs);
        allRemoveBtn.setOnClickListener(new OnClickListener() {

            @SuppressLint("InflateParams")
            @Override
               public void onClick(View arg0) {

                    LayoutInflater layoutInflater  = (LayoutInflater) getActivity().getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    View popupView = layoutInflater.inflate(R.layout.popup, null);

                    final PopupWindow popupWindow = new PopupWindow(popupView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
                    popupWindow.showAtLocation(popupView, Gravity.CENTER, 0, 0);

                    Button btnNo = (Button) popupView.findViewById(R.id.btn_no);
                    btnNo.setOnClickListener(new Button.OnClickListener(){

                         @Override
                         public void onClick(View v) {

                             // Close the pop-up window
                             popupWindow.dismiss();
                         }
                    });

                    Button btnYes = (Button) popupView.findViewById(R.id.btn_yes);
                    btnYes.setOnClickListener(new Button.OnClickListener(){

                         @Override
                         public void onClick(View v) {

                             // Delete All from Table
                             controller.deleteAllArticle(db, "Favourites");

                             // Close the pop-up window
                             popupWindow.dismiss();

                             // Reload current fragment
                             articles = controller.getAllArticles();
                             adapter.notifyDataSetChanged();

                             // Hide the Image Button
                             allRemoveBtn.setVisibility(View.INVISIBLE);
                         }
                    });
                    popupWindow.showAsDropDown(allRemoveBtn, 50, -30);
                }
        });

    }
    return rootView;
}

public class CustomListAdapter extends ArrayAdapter<HashMap<String, String>>
{
    Context context;

    public CustomListAdapter(Context context, int resourceId)
    {   
        super(context, resourceId);
        this.context = context;
    }

    @Override
    public int getCount() {
        return articles.size();
    }

    @Override
    public long getItemId(int position) {
        return position;
    }
    @SuppressWarnings("unused")
    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        View row = convertView;
        ViewHolder view_holder;
        final HashMap<String, String> rowItem = articles.get(position);

        if (row == null) 
        {
            LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.lv_fav_layout, null);

            view_holder = new ViewHolder();


            view_holder.iv_thumb = (ImageView) row.findViewById(R.id.iv_thumb);
            view_holder.tv_article_title = (TextView) row.findViewById(R.id.tv_article_title);
            view_holder.tv_article_date = (TextView) row.findViewById(R.id.tv_article_date);
            view_holder.tv_article_synopsis = (TextView) row.findViewById(R.id.tv_article_synopsis);
            view_holder.iv_rem_favs_single =(ImageButton)row.findViewById(R.id.iv_rem_favs_single);

            row.setTag(view_holder);
        }
        else
        {
            view_holder = (ViewHolder) row.getTag();
            view_holder.iv_thumb.setImageBitmap(null);
        }

        row.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {

                selectItem(position);
            }
        });

        // Getting the Article ID of selected item
        final String articleId = articles.get(position).get("ArticleId");

        // Setting of the Image
        String imgUrl = articles.get(position).get("ArticleUrl");
        new DownloadImageTask(view_holder.iv_thumb).execute(imgUrl);

        // Setting the Title
        view_holder.tv_article_title.setText(articles.get(position).get("ArticleTitle"));

        // Setting the Date
        view_holder.tv_article_date.setText(articles.get(position).get("ArticleDate"));

        // Setting the Synopsis of the article
        view_holder.tv_article_synopsis.setText(articles.get(position).get("ArticleSynopsis"));

        // Set the onclick listener for the remove favourite item
        view_holder.iv_rem_favs_single.setTag(view_holder.iv_rem_favs_single);
        view_holder.iv_rem_favs_single.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(final View arg0) {
                LayoutInflater layoutInflater  = (LayoutInflater) getActivity().getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                View popupView = layoutInflater.inflate(R.layout.popup, null);

                final PopupWindow popupWindow2 = new PopupWindow(popupView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
                popupWindow2.showAtLocation(popupView, Gravity.CENTER, 0, 0);

                Button btnNo = (Button) popupView.findViewById(R.id.btn_no);
                btnNo.setOnClickListener(new Button.OnClickListener(){

                     @Override
                     public void onClick(View v) {

                         // DO NOT DELETE ANYTHING

                         // Close the pop-up window
                         popupWindow2.dismiss();
                     }
                });

                Button btnYes = (Button) popupView.findViewById(R.id.btn_yes);
                btnYes.setOnClickListener(new Button.OnClickListener(){

                     @Override
                     public void onClick(View v) {

                         // Delete selected item from the Table
                         controller.deleteArticle(articleId);

                         // Close the pop-up window
                         popupWindow2.dismiss();

                         // Reload current fragment
                         articles = controller.getAllArticles();
                         adapter.notifyDataSetChanged();

                         // Set the Image of the Image Button to selected
                         //((ImageButton) arg0.getTag()).setImageResource(R.drawable.remove_favourite_selected);

                         if (articles.isEmpty()) {
                            // Do not show the Delete all image button
                            allRemoveBtn.setVisibility(View.INVISIBLE);
                         }
                     }
                });

                popupWindow2.showAsDropDown((ImageButton) arg0.getTag(), 50, -30);
            }
        });

        return row;
    }

    private class ViewHolder{
        ImageView iv_thumb;
        TextView tv_article_title;
        TextView tv_article_date;
        TextView tv_article_synopsis;
        ImageButton iv_rem_favs_single;
    }
}

// If the listview item is selected, it loads the next fragment
private void selectItem(int position) {

        Log.d("POSITION","Position: " + position);

        // update the main content by replacing fragmentss
        FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();


        FullArticleFragment fragment = new FullArticleFragment();
        fragment.article = articles.get(position);

        // Replace whatever is in the fragment_container view with this fragment,
        // and add the transaction to the back stack so the user can navigate back
        transaction.replace(R.id.fragment_container, fragment);
        transaction.addToBackStack(null);

        // Commit the transaction
        transaction.commit();
}

// Download the image from the url stored in the database
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    ImageView bmImage;

    public DownloadImageTask(ImageView bmImage) {
        this.bmImage = bmImage;
    }

    @Override
    protected Bitmap doInBackground(String... urls) {
        String urldisplay = urls[0];
        Bitmap mIcon11 = null;
        InputStream in = null;

            try {
                in = new java.net.URL(urldisplay).openStream();

                // Log.d("IMAGEURL","DIT - Url: " + urldisplay);

                mIcon11 = BitmapFactory.decodeStream(in);
                in.close();
            } 
            catch (Exception e) 
            {
                Log.e("Error", e.getMessage());
                e.printStackTrace();
            }

        return mIcon11;
    }

    @Override
    protected void onPostExecute(Bitmap result) {
        bmImage.setImageBitmap(result);
    }
}
}

Can anyone help me solve with this problem.

Upvotes: 2

Views: 275

Answers (1)

GioLaq
GioLaq

Reputation: 2547

You are not checking if the image is in the same position or not. Try something like this:

// Download the image from the url stored in the database
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    ImageView bmImage;
    int position;

    public DownloadImageTask(ImageView bmImage, int position) {
        this.bmImage = bmImage;
        this.position = position;
        ivPic.setTag(position);
        bmImage.setImageBitmap(null);
    }

    @Override
    protected Bitmap doInBackground(String... urls) {
        String urldisplay = urls[0];
        Bitmap mIcon11 = null;
        InputStream in = null;

            try {
                in = new java.net.URL(urldisplay).openStream();

                // Log.d("IMAGEURL","DIT - Url: " + urldisplay);

                mIcon11 = BitmapFactory.decodeStream(in);
                in.close();
            } 
            catch (Exception e) 
            {
                Log.e("Error", e.getMessage());
                e.printStackTrace();
            }

        return mIcon11;
    }


    @Override
    protected void onPostExecute(Bitmap result) {
        super.onPostExecute(result);
        if(result != null && ((Integer)getTag) == this.position)
        bmImage.setImageBitmap(result); 
    }
}

Upvotes: 1

Related Questions