快速显示从服务器下载的图像 [英] Show images downloaded from a server in a fast way

查看:97
本文介绍了快速显示从服务器下载的图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个场景,我想显示从服务器下载的多个图像.我正在尝试下载纹理并将其存储在列表中.当for循环完成运行时,我按名称对列表进行排序,然后从列表中实例化RawImage,但不起作用.我在做什么错了?

I have a scene where I'd like to show multiple images downloaded from a server. I'm trying to download the textures and store them in a List. When the for loop finish running, I sort the List by name and then I instantiate the RawImage from the List, but doesn't works. What am I doing wrong?

public GameObject contentRef;
public RawImage imgPrefab;

void Start()
{
    StartCoroutine(DownloadtheFiles());
}

public IEnumerator DownloadtheFiles()
{
    yield return null;

    List<string> photolist = ES2.LoadList<string>("myPhotos.txt");

    for (int i = 0; i < photolist.Count; i++)
    {
        //Don't capture i variable
        int index = i;

        bool reqDone = false;

        new GetUploadedRequest()

            .SetUploadId(photolist[index])
            .Send((response) =>
                {
                    StartCoroutine(DownloadImages(response.Url, index,
                        (status) => { reqDone = status; }));


                    //return null;
                });

        //Wait in the for loop until the current request is done
        while (!reqDone)
            yield return null;
    }
}

public IEnumerator DownloadImages(string downloadUrl, int index, Action<bool> done)
{
    var www = new WWW(downloadUrl);
    yield return www;

    //Get the downloaded image
    Texture2D tex = new Texture2D(4, 4);
    www.LoadImageIntoTexture(tex);

    List <Texture2D> texList = new List <Texture2D> ();

    for (int i = 0; i < tex.Count; i++)
    {
        texList.Add (tex);
    }

    texList = texList.OrderBy(mtex => mtex.name).ToList();

    for (int i = 0; i < tex.Count; i++)
    {
        RawImage newImg = Instantiate(imgPrefab, contentRef.transform);
        //Change the name
        newImg.name = "Image-" + index;
        //Apply the downloaded image
        newImg.texture = tex;
    }

    //Done
    if (done != null)
        done(true);
}

}

推荐答案

您的RawImage代码应在DownloadImages函数外部完成,因为调用DownloadImages是为了从for循环中的URL下载图像. RawImage实例化应仅在for循环完成之后进行.

Your RawImage code should be done outside the DownloadImages function because DownloadImages is called to download image from the url in the for loop. The RawImage instantiation should be done only after the for loop has completed.

此外,使用texList.OrderBy(mtex => mtex.name).ToList();也不起作用,因为您的字符串同时包含string和int且格式为"Image-" + 0;".您将需要一个自定义函数来执行此操作通过拆分stringint然后用int排序.

Also, using texList.OrderBy(mtex => mtex.name).ToList(); wouldn't work because your string contains both string and int and is in this format "Image-" + 0;". You will need a custom function to do that by splitting the string and int then sorting with the int.

最后,在for循环完成运行之后,需要一种方法来实例化RawImages之前确定所有映像均已完成下载.您可以通过使用数组或bool的列表来实现此目的,其中List<string> photolist的大小应包含要下载的图像链接.每次下载完成后,将该布尔数组传递给DownloadImages并使用index参数将其设置为true.

Finally, after the for loop has finished running, you need a way to determine that all images has finished downloading before instantiating the RawImages. You can do this by using array or List of bool with the size of the List<string> photolist that contains the link of images to download. Pass that array of bool to the DownloadImages and use the index argument to set it to true when each download is done.

public GameObject contentRef;
public RawImage imgPrefab;

List<Texture2D> downloadedTextures = new List<Texture2D>();

void Start()
{
    DownloadtheFiles();
}

public void DownloadtheFiles()
{

    List<string> photolist = ES2.LoadList<string>("myPhotos.txt");

    //Used to determine when were done downloading
    bool[] doneDownloading = new bool[photolist.Count];

    //Download images only.Don't instantiate anything
    for (int i = 0; i < photolist.Count; i++)
    {
        //Don't capture i variable
        int index = i;

        new GetUploadedRequest()

            .SetUploadId(photolist[index])
            .Send((response) =>
            {
                StartCoroutine(DownloadImages(response.Url, index, doneDownloading));
            });
    }

    //Instantiate the download images
    StartCoroutine(InstantiateImages(doneDownloading));
}

//Instantiates the downloaded images after they are done downloading
IEnumerator InstantiateImages(bool[] downloadStatus)
{
    //Wait until all images are done downloading
    for (int i = 0; i < downloadStatus.Length; i++)
    {
        while (!downloadStatus[i])
            yield return null;
    }

    //Sort the images by string
    sort(ref downloadedTextures);

    //Now, instantiate the images
    for (int i = 0; i < downloadedTextures.Count; i++)
    {
        //Instantiate the image prefab GameObject and make it a child of the contentRef
        RawImage newImg = Instantiate(imgPrefab, contentRef.transform);

        //Apply the downloaded image
        newImg.texture = downloadedTextures[i];

        //Update name so that we can see the names in the Hierarchy
        newImg.name = downloadedTextures[i].name;
    }

    //Clear List for next use
    downloadedTextures.Clear();
}

//Sort the downloaded Textures by name
void sort(ref List<Texture2D> targetList)
{
    var ordered = targetList.Select(s => new { s, Str = s.name, Split = s.name.Split('-') })
    .OrderBy(x => int.Parse(x.Split[1]))
    .ThenBy(x => x.Split[0])
    .Select(x => x.s)
    .ToList();

    targetList = ordered;
}

public IEnumerator DownloadImages(string downloadUrl, int index, bool[] downloadStatus)
{
    //Download image
    var www = new WWW(downloadUrl);
    yield return www;

    //Get the downloaded image and add it to the List
    Texture2D tex = new Texture2D(4, 4);
    //Change the name
    tex.name = "Image-" + index;
    www.LoadImageIntoTexture(tex);
    downloadedTextures.Add(tex);

    downloadStatus[index] = true;
}

这篇关于快速显示从服务器下载的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆