I am working on Sales App of Windows Store app. I want to apply lazy loading for my product module.
When Product page open it get product from backend and show in ListBox control. It takes time everytime to load. I think main reason is when I check for the image exists on given url.
Here is my code and class:
private async Task getAllProductDetails()
{
var resultproductlist = await client.PostAsync(session.Values["URL"] + "/magemobpos/product/getProductList", contents);
if (resultproductlist.IsSuccessStatusCode)
{
string trys = resultproductlist.Content.ReadAsStringAsync().Result;
List<Productlistdata> objProducts = JsonConvert.DeserializeObject<ProductlistResponse>(trys).productlistdata;
Productlistdata Product;
//all product are in objProducts
foreach (var item in objProducts)
{
bool imageexist = false;
//check if image exist on given url or not
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(item.image.ToString()));
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
int imagelength = Convert.ToInt32(response.ContentLength);
if (imagelength > 0)
imageexist = true;
else
imageexist = false;
}
}
catch (Exception)
{
imageexist = false;
}
//if image not exist, it get default image
if (item.image.ToString().ToLower().Equals("n/a") || imageexist == false)
{
item.image = "Images/NoDataImages/ico-no-orders.png";
}
Product = new Productlistdata()
{
image = item.image,
name = item.name,
price = item.price,
sku = item.sku,
type = item.type[0],
id = item.id
};
//add all product in lstProduct. lstProduct is ListBox Control
lstProduct.Items.Add(Product);
}
}
}
Class:
public class Productlistdata
{
public string id { get; set; }
public string sku { get; set; }
public string name { get; set; }
public string status { get; set; }
public string qty { get; set; }
public string price { get; set; }
public string image { get; set; }
public string type { get; set; }
public string full_productname { get; set; }
}
Can anybody suggest me how to apply lazy loading? I don't know exactly but I think it can apply to bind image once the list is loaded.
I know that you dint ask for it but I ll strongly suggest you to look into Bindings I believe it will help you a lot thinking what you are trying to build. So I ll start by changing some of your code using bindings and then go to the real solution.
Here is what you can try and do:
First remove this code:
bool imageexist = false;
//check if image exist on given url or not
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(item.image.ToString()));
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
int imagelength = Convert.ToInt32(response.ContentLength);
if (imagelength > 0)
imageexist = true;
else
imageexist = false;
}
}
catch (Exception)
{
imageexist = false;
}
Second Step is to get rid of this code
//add all product in lstProduct. lstProduct is ListBox Control
lstProduct.Items.Add(Product);
Now add on top of you page.xaml.cs an ObservableCollection
private ObservableCollection<Productlistdata> productlist = new ObservableCollection<Productlistdata>();
public ObservableCollection<Productlistdata> Productlist
{
get { return productlist ?? (productlist= new ObservableCollection<Productlistdata>()); }
set { productlist= value; }
}
Now you either bind that list in the list box like this
<ListBox ItemsSource="{Binding Productlist}"/>
or In the Contractor of your page do
lstProduct.ItemsSource = Productlist;
That way Productlist is binded to your ListBox and when you add or remove items will it will be updated automatically.
Now you can skip all the above but I suggest you to look into Bindings it powerfull and will solve many of your problems when you get the idea of they work.
Now we will add the first code we removed in your ProductListdata
public class Productlistdata
{
public string id { get; set; }
public string sku { get; set; }
public string name { get; set; }
public string status { get; set; }
public string qty { get; set; }
public string price { get; set; }
public string image { get; set; }
public string type { get; set; }
public string full_productname { get; set; }
public async void CheckImage()
{
bool imageexist = false;
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(image));
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
int imagelength = Convert.ToInt32(response.ContentLength);
if (imagelength > 0)
imageexist = true;
else
imageexist = false;
}
}
catch (Exception)
{
imageexist = false;
}
if (!imageexist)
{
image = "Images/NoDataImages/ico-no-orders.png";
}
}
}
And populate your List
private async Task getAllProductDetails()
{
var resultproductlist = await client.PostAsync(session.Values["URL"] + "/magemobpos/product/getProductList", contents);
if (resultproductlist.IsSuccessStatusCode)
{
string trys = resultproductlist.Content.ReadAsStringAsync().Result;
List<Productlistdata> objProducts = JsonConvert.DeserializeObject<ProductlistResponse>(trys).productlistdata;
//all product are in objProducts
foreach (var item in objProducts)
{
Productlistdata Product = new Productlistdata()
{
image = item.image,
name = item.name,
price = item.price,
sku = item.sku,
type = item.type[0],
id = item.id
};
Product.CheckImage();
Productlist.Add(Product);
}
}
}
Product.CheckImage();
will not be awaited. So the Items in the list will load really fast because nothing is awaited in the foreach loop. Product.CheckImage();
will run on another thread at later time.
Finally because image might change after the data is loaded on the ListBoxa(when image wasnt fount) you will have to Notify the UI that a property has changed. To do that you will have to use INotifyPropertyChanged. You can take a look in an other answer of mine how to do that here