webview shows wrong values inside listview

653 views Asked by At

i have a listview for showing products (product Name, product Price and product Description). I want to show the product description in a webview because i use html code (images,tables,video etc).

Everything is ok on the products list except the product description on the WebView. When i scroll the listview on the products that they are not visible, the product Description(WebView) is completely wrong, actually it shows descriptions from previous products.

The problem it is inside the GetView function, and although i use a viewHolder class , it still the problem remailns. Below i show the code snippet of the Getview and the viewholder class :

/////THE VIEWHOLDER CLASS THAT HOLDS THE UI COMPONENTS//////////////////

         private class ViewHolder {
            TextView prName;
            WebView prDescription;
            TextView product_descr2;//for test, this shows always the correct pr. descr.
            TextView prfprice;
            ImageView prImage;
            ProgressBar prProgressBar;
            int ProdPosition;               
        }

//////THE GETVIEW() FUNCTION , WHERE I LOAD EACH PRODUCT VALUES///////

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final ViewHolder viewHolder;

            View view = convertView;
            final ProductsData info = getItem(position);

            if (view == null) {
                // Product row
                view = mInflater.inflate(R.layout.productslistitem_layout, null);

                viewHolder = new ViewHolder();
                assert view != null;

                viewHolder.prName = (TextView) view.findViewById(R.id.product_name);
                viewHolder.prDescription = (WebView) view.findViewById(R.id.webView1);
                viewHolder.product_descr2 = (TextView)view.findViewById(R.id.product_descr2);
                viewHolder.prDescription.setFocusable(false);

                //final price
                viewHolder.prfprice = (TextView) view.findViewById(R.id.product_fprice);
                viewHolder.prImage = (ImageView) view.findViewById(R.id.product_image);
                viewHolder.prProgressBar = (ProgressBar)view.findViewById(R.id.pbProduct);

                view.setTag(viewHolder);

            }else
                viewHolder = (ViewHolder) view.getTag();

            MainActivity.imageLoaderProducts.displayImage(info.getPrUrl(), viewHolder.prImage, options, new SimpleImageLoadingListener(){
                 @Override
                 public void onLoadingStarted(String imageUri, View view) {
                     viewHolder.prProgressBar.setProgress(0);
                     viewHolder.prProgressBar.setVisibility(View.VISIBLE);
                 }

                 @Override
                 public void onLoadingFailed(String imageUri, View view,
                         FailReason failReason) {
                     viewHolder.prProgressBar.setVisibility(View.GONE);
                 }

                 @Override
                 public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
                    viewHolder.prProgressBar.setVisibility(View.GONE);
                    viewHolder.prName.setText(info.getPrName());  //PRODUCT NAME
                    viewHolder.product_descr2.setText(info.getPrDescr()));//PRODUCT DESCR, CORRECT VALUES

                    String header = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>";
                    viewHolder.prDescription.setWebViewClient(new WebViewClient());
                    viewHolder.prDescription.getSettings().setJavaScriptEnabled(true);
                    //ENCODING UTF-8
                    viewHolder.prDescription.getSettings().setDefaultTextEncodingName("utf-8");

                    viewHolder.prDescription.loadData(header +"<div style='background-color:#fff'>"+ info.getPrDescr()+"</div>", "text/html; charset=utf-8", null);//WBVIEW SHOW WRONG PR.DESCR.
             }, new ImageLoadingProgressListener() {
                 @Override
                 public void onProgressUpdate(String imageUri, View view, int current,int total) {
                     viewHolder.prProgressBar.setProgress(Math.round(100.0f * current / total));
                 }
             }
                );
            return view;
        }

The product_descr2(TextView) shows the correct product description but the prDescription(WebView) shows the correct description only for the first product of the list. Is it a bug of WebView component or am i doing something wrong?

If anyone knows any solution please give a hand.

/*******************************/

I noticed that if i add convertview = null; into the getView, it loads the correct values into the WebViews but it is too slow. i show the code of the products file. I use the universal image loader for lazy loading of the product images.

/******************PRODUCTS FILE************************************************************/

import java.util.ArrayList;

public class FragmentProducts extends Fragment implements
        OnItemClickListener {

    private ArrayList<ProductsData> productsList;
    private ArrayList<ProductBitmapData> ProductBitmapList;
    private LayoutInflater mInflater;
    private ProductsListAdapter pAdapter;
    private GridView lvProducts;
    private ImageButton btnRefreshProducts;

    private String VarTitle;//vartitle for the cart
    private String VarId;//varId for the cart
    private float VarPrice;//varPrice for the cart

    //NEW for universal image loader
    private DisplayImageOptions options;

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onViewCreated(view, savedInstanceState);
        //change fonts
        TextView tvProductsHeader = (TextView)getActivity().findViewById(R.id.tvProductsHeader);
        Utils.TypeFace(tvProductsHeader, getActivity().getAssets());
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onActivityCreated(savedInstanceState);

        mInflater = getActivity().getLayoutInflater();
        pAdapter = new ProductsListAdapter(getActivity(), productsList);
        lvProducts.setAdapter(pAdapter);

    }

    public static final FragmentProducts newInstance(
            ArrayList<ProductsData> productsList,
            ArrayList<ProductBitmapData> ProductBitmapList) {
        FragmentProducts fr = new FragmentProducts();
        Bundle args = new Bundle();
        args.putSerializable("products", productsList);
        args.putSerializable("bitmaps", ProductBitmapList);
        fr.setArguments(args);

        return fr;
    }

    public static final FragmentProducts newInstance(
            ArrayList<ProductsData> productsList) {
        //OLD FragmentProductsList fr = new FragmentProductsList();
        FragmentProducts fr = new FragmentProducts();
        Bundle args = new Bundle();
        args.putSerializable("products", productsList);
        fr.setArguments(args);

        return fr;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.productsList = (ArrayList<ProductsData>) (getArguments() != null ? getArguments()
                .getSerializable("products") : null);
        this.ProductBitmapList = (ArrayList<ProductBitmapData>) (getArguments() != null ? getArguments()
                .getSerializable("bitmaps") : null);

        //display options
        options = new DisplayImageOptions.Builder()
            .showImageOnLoading(R.drawable.ic_stub)
            .showImageForEmptyUri(R.drawable.ic_empty)
            .showImageOnFail(R.drawable.ic_error)
            .cacheInMemory(true)
            .cacheOnDisk(true)
            .considerExifParams(true)
            .bitmapConfig(Bitmap.Config.RGB_565)
            .build();
    }

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

        View view = inflater.inflate(R.layout.productslist_layout, container,
                false);

        lvProducts = (GridView) view.findViewById(R.id.glist);
        lvProducts.setOnItemClickListener(this);
        btnRefreshProducts = (ImageButton) view
                .findViewById(R.id.btnRefreshProducts);
        btnRefreshProducts.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                pAdapter = new ProductsListAdapter(getActivity(), productsList);
                lvProducts.setAdapter(pAdapter);

            }
        });

        return view;
    }

    // CUSTOM ARRAY ADAPTER FOR THE LIST of CATEGORY ITEMS
    public class ProductsListAdapter extends ArrayAdapter<ProductsData> {

        public ProductsListAdapter(Context context, ArrayList<ProductsData> data) {
            super(context, 0, data);
        }

        private class ViewHolder {
            TextView prName;
            WebView prDescription;              
            TextView prfprice;
            ImageView prImage;
            ProgressBar prProgressBar;
            Spinner PrVariants1;        
            Spinner PrVariants2;
            int ProdPosition;

            //adapters
            ArrayAdapter<String> var1Adapter;
            ArrayAdapter<String> var2Adapter;
        }

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

        @Override
        public ProductsData getItem(int position) {
            return super.getItem(position);
        }

        @Override
        public long getItemId(int position) {
            return super.getItemId(position);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final ViewHolder viewHolder;
            /*Clear convert view , and the WEBVIEW(DESCRIPTION) WORKS FINE! **/
            /*BUT IT IS TOO SLOW BECAUSE, IT LOADS FROM THE START EACH TIME*/
            convertView = null;
            /*************************/

            View view = convertView;
            final ProductsData info = getItem(position);

            if (view == null) {
                // Product row
                view = mInflater.inflate(R.layout.productslistitem_layout, null);

                viewHolder = new ViewHolder();
                assert view != null;

                viewHolder.prName = (TextView) view.findViewById(R.id.product_name);
                viewHolder.prDescription = (WebView) view.findViewById(R.id.webView1);

                viewHolder.prDescription.setFocusable(false);

                //starting price
                /*viewHolder.prsprice = (TextView) view.findViewById(R.id.product_sprice);*/
                //final price
                viewHolder.prfprice = (TextView) view.findViewById(R.id.product_fprice);
                viewHolder.prImage = (ImageView) view.findViewById(R.id.product_image);
                viewHolder.prProgressBar = (ProgressBar)view.findViewById(R.id.pbProduct);

                viewHolder.PrVariants1 = (Spinner) view.findViewById(R.id.spOptions1);
                viewHolder.PrVariants1.setFocusable(false);

                viewHolder.PrVariants2 = (Spinner) view.findViewById(R.id.spOptions2);
                viewHolder.PrVariants2.setFocusable(false);

                view.setTag(viewHolder);

            }else
                viewHolder = (ViewHolder) view.getTag();

            MainActivity.imageLoaderProducts.displayImage(info.getPrUrl(), viewHolder.prImage, options, new SimpleImageLoadingListener(){
                 @Override
                 public void onLoadingStarted(String imageUri, View view) {
                     viewHolder.prProgressBar.setProgress(0);
                     viewHolder.prProgressBar.setVisibility(View.VISIBLE);
                 }

                 @Override
                 public void onLoadingFailed(String imageUri, View view,
                         FailReason failReason) {
                     viewHolder.prProgressBar.setVisibility(View.GONE);
                 }

                 @Override
                 public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
                    viewHolder.prProgressBar.setVisibility(View.GONE);
                    viewHolder.prName.setText(info.getPrName());

                    //SHOW WEBVIEW PRODUCT VALUE
                    String header = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>";
                    viewHolder.prDescription.setWebViewClient(new WebViewClient());
                    viewHolder.prDescription.getSettings().setJavaScriptEnabled(true);

                    //ENCODING UTF-8
                    viewHolder.prDescription.getSettings().setDefaultTextEncodingName("utf-8");

            /**HERE IS THE PROBLEM ,I LOAD THE info.PrComments(product description)*/
                    viewHolder.prDescription.loadData(header +"<div style='background-color:#fff'>"+ info.getPrComments()+"</div>", "text/html; charset=utf-8", null);
           /****************AND IF I SCROLL THE WEBVIEW VALUES ARE CONFUSED ***********/ 


                    /********START FILL VARIANTS 1 & 2***********/
                    viewHolder.var1Adapter = new ArrayAdapter<String>(getActivity(),android.R.layout.simple_spinner_item);
                    viewHolder.var2Adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_item);

                    //product id
                    int tempPrid = info.getPrID();

                    //new variants1
                    //LOAD variant1
                    for(int i = 0; i < info.getVariantsItems().size(); i ++){
                        viewHolder.var1Adapter.add(info.getVariantsItems().get(i).getVarOptions1());
                    }

                    //IF VARIANT2 IS NULL, View.GONE
                    if(info.getVariantsItems2().get(0).getVarOptions2() != null){

                        for(int i = 0; i < info.getVariantsItems2().size(); i ++){
                            viewHolder.var2Adapter.add(info.getVariantsItems2().get(i).getVarOptions2());
                        }
                        viewHolder.var2Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                        viewHolder.PrVariants2.setAdapter(viewHolder.var2Adapter);
                    }//end if
                    else{
                        viewHolder.PrVariants2.setVisibility(View.GONE);
                    }//end else variant2

                    viewHolder.var1Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                    viewHolder.PrVariants1.setAdapter(viewHolder.var1Adapter);

                    //add eventListener on variants1 listbox
                    viewHolder.PrVariants1.setOnItemSelectedListener(new OnItemSelectedListener() {
                    @Override
                    public void onItemSelected(AdapterView<?> parent,
                            View arg1, int pos, long arg3) {
                        //GET VALUES FROM spinner1
                        String tempOption1 = parent.getItemAtPosition(pos).toString();

                        //initialize 
                        String tempOption2=null;

                        //CHECK IF SPINNER2 IS VISIBLE(IF IT IS VISIBLE ,IT HAS VALUE)
                        if (viewHolder.PrVariants2.getVisibility() != View.GONE){

                            if (viewHolder.PrVariants2.getSelectedItem() != null){
                                tempOption2 = viewHolder.PrVariants2.getSelectedItem().toString();
                            }
                        }


                        if (tempOption2 !=null)
                        {   
                            VarTitle = tempOption1 + "/" + tempOption2;
                        }else
                            VarTitle = tempOption1;

                        ArrayList<String> res =  MainApplication.dbHelper.checkVariation(VarTitle, Integer.toString(info.getPrID()));

                        //IF VARIATION DOES NOT EXIST , price field = N/A
                        if (res.isEmpty())
                            viewHolder.prfprice.setText("N/A");
                        else{
                            viewHolder.prfprice.setText(res.get(1) + "€");

                            VarId = res.get(0);//get the variantId for the cart
                            VarPrice = Float.valueOf(res.get(1));//get the variant price for the cart
                        }
                    }
                    @Override
                    public void onNothingSelected(AdapterView<?> arg0) {}
                    });

                    //add event listener on variants2 listbox
                    viewHolder.PrVariants2.setOnItemSelectedListener(new OnItemSelectedListener() {
                        @Override
                        public void onItemSelected(AdapterView<?> parent,
                                View arg1, int pos, long arg3) {                            

                            //initialize
                            String tempOption2 = null;

                            if(parent.getItemAtPosition(pos) != null){
                                tempOption2 = parent.getItemAtPosition(pos).toString();
                            }

                            //GET SPINNER1 VALUE
                            String tempOption1 =  viewHolder.PrVariants1.getSelectedItem().toString();
                            if(tempOption2 != null)
                            {
                                VarTitle = tempOption1 + "/" + tempOption2;
                            }else
                                VarTitle = tempOption1;

                            ArrayList<String> res =  MainApplication.dbHelper.checkVariation(VarTitle, Integer.toString(info.getPrID()));

                            ///IF VARIATION DOES NOT EXIST , price field = N/A
                            if (res.isEmpty())
                                viewHolder.prfprice.setText("N/A");
                            else{
                                viewHolder.prfprice.setText(res.get(1) + "€");

                                VarId = res.get(0);//get the variantId for the cart
                                VarPrice = Float.valueOf(res.get(1));//get the variant price for the cart
                            }

                        }
                        @Override
                        public void onNothingSelected(AdapterView<?> arg0) {}
                    });
                    /********END FILL VARIANTS 1 & 2*************/
                 }
             }, new ImageLoadingProgressListener() {
                 @Override
                 public void onProgressUpdate(String imageUri, View view, int current,
                         int total) {
                     viewHolder.prProgressBar.setProgress(Math.round(100.0f * current / total));
                 }
             }
                    );

            return view;
        }
    }
1

There are 1 answers

1
plotpoint On

Don't use ViewHolder! => http://blog.xebia.com/2013/07/22/viewholder-considered-harmful/

try this: ...without if(convert == null){ ....
just inflate convertView

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

                convertView = Inflater.inflate(R.layout.productslistitem_layout, null);
...
...