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;
}
}
Don't use ViewHolder! => http://blog.xebia.com/2013/07/22/viewholder-considered-harmful/
try this: ...without if(convert == null){ ....
just inflate convertView