我正在开发Windows应用商店应用的销售应用。我想为我的产品模块应用延迟加载。
当产品页面打开时,它从后端获取产品并在ListBox控件中显示。 每次加载都需要时间。我认为主要原因是当我检查给定网址上存在的图像时。
这是我的代码和类:
SysDatabaseLogWizard
类别:
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);
}
}
}
有人可以建议我如何应用延迟加载吗?我不完全确切,但我认为一旦列表加载就可以应用于绑定图像。
答案 0 :(得分:0)
我建议您更改查询,
首先代替getAllProductDetails执行getAllProductID 所以你在哪里
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;
你会做的
var resultproductlist = await client.PostAsync(session.Values["URL"] + "/magemobpos/product/getProductID", contents);
if (resultproductlist.IsSuccessStatusCode)
{
string trys = resultproductlist.Content.ReadAsStringAsync().Result;
List<int> objProducts = JsonConvert.DeserializeObject<ProductlistResponse>(trys).productlistdata;
LazyProductlistdata Product;
其次创建一个包装器
public LazyProductlistdata
{
public string id { get; set; }
private Lazy<Productlistdata> data = new Lazy<Productlistdata>(()=>Productlistdata.CreateFromID(id));
public Productlistdata Data
{
get{return data.Value;}
}
}
展开它,以便包装器包含排序所需的信息
最后更改构造函数或为Productlistdata创建工厂,以便从源获取单个记录
public class Productlistdata
{
public static Productlistdata CreateFromID(int id)
{
//Return single Productlistdata from webservice
}
}
注意:延迟加载会增加整体加载时间,优势在于它不是一大块时间而是几个较小的加载时间
答案 1 :(得分:0)
我建议使用Converter来提供占位符see here。
您还可以使用IsAsync = True来装饰Image.Source绑定 - 这样就不会阻止主线程
答案 2 :(得分:0)
您可以使用ImageFailed事件来指定图像占位符
foreach (var item in objProducts)
{
var bitmap = new BitmapImage();
bitmap.ImageFailed += (s, e) => bitmap.UriSource = defaultImageUri;
bitmap.UriSource = new Uri(item.image);
item.Add(bitmap);
//set decodepixelwidth and dicodepixelheight correctly to avoid outofmemory exception
}
答案 3 :(得分:0)
我知道你要求它,但我强烈建议你研究Bindings我相信它会帮助你思考你想要建立什么。因此,我将首先使用绑定更改一些代码,然后转到真正的解决方案。
以下是您可以尝试做的事情:
首先删除此代码:
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;
}
第二步是摆脱这段代码
//add all product in lstProduct. lstProduct is ListBox Control
lstProduct.Items.Add(Product);
现在在page.xaml.cs上添加一个ObservableCollection
private ObservableCollection<Productlistdata> productlist = new ObservableCollection<Productlistdata>();
public ObservableCollection<Productlistdata> Productlist
{
get { return productlist ?? (productlist= new ObservableCollection<Productlistdata>()); }
set { productlist= value; }
}
现在您可以像这样
在列表框中绑定该列表<ListBox ItemsSource="{Binding Productlist}"/>
或在页面的承包商中
lstProduct.ItemsSource = Productlist;
这样,Productlist会绑定到ListBox,当您添加或删除项目时,它会自动更新。
现在你可以跳过以上所有内容,但我建议你研究Bindings它的强大功能,并在你了解它们的工作原理时解决你的许多问题。
现在我们将添加我们在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";
}
}
}
填充您的列表
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();
将不会被等待。所以列表中的项目加载速度非常快,因为在foreach循环中没有等待的东西。 Product.CheckImage();
将在以后的另一个线程上运行。
最后,因为在ListBoxa上加载数据后图像可能会发生变化(当图像不是fount时),您必须通知UI属性已更改。为此,您必须使用INotifyPropertyChanged。你可以看看我的另一个答案如何做here