【问题标题】:How to download the series of Images from Server如何从服务器下载系列图像
【发布时间】:2015-11-03 14:15:15
【问题描述】:

我有自己的服务器,我想自动一张一张地下载图像。 现在我所尝试的是将图像下载并保存在设备上,并且可以 100% 完美运行。但这适用于单个图像,这是好的link。但它可以工作,但只下载一张图片,或者你可以说一个图片一个链接。

我想到了一个想法,那就是制作Url的字符串数组,然后应用for循环,然后它会下载并执行那么多Asynctask。

但这不是一个好习惯,因为它会启动太多异步任务。

我想要什么

  1. 我希望如果我有 10 个 Url ,那么它应该从 第一个 url 到最后一个 url 但一个接一个,我的意思是当 First Image 有 已下载然后它应该在保存后启动第二个图像 设备上的第一张图片。

  2. 它应该集体显示所有图像的进度条进度。并且应该更新进度假设有 10 个图像,那么当第一个图像成功下载时它应该显示 10% 完成,如果已经下载了 2 个图像,它应该显示 20%。

请给我源代码或任何可以帮助我的东西。谢谢。

【问题讨论】:

  • 你必须在服务器端做逻辑。 Android 只是一个客户端应用程序。它只下载,服务器必须决定必须为客户端应用程序发送多少文件。

标签: android android-asynctask android-async-http


【解决方案1】:

为什么不在 aysncTask 中尝试这个 for 循环,因为这不会创建多个 aysncTask 对象,减少内存使用。

 public class httpDownloadImages extends AsyncTask<Void,Void,String> {
        Bitmap myBitmap[]=new Bitmap[10];
@Override
    protected void onPreExecute() {
        super.onPreExecute();
        showProgressDialog();

    }

        @Override
        protected String doInBackground(Void... params) {
            try {

                for(int i=1; i<=10; i++){
                    String src="http://"+ip+"/images/"+i+".jpg";
                    java.net.URL url = new java.net.URL(src);
                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    connection.setDoInput(true);
                    connection.connect();
                    InputStream input = connection.getInputStream();
                    myBitmap[i] = BitmapFactory.decodeStream(input);
                    if(myBitmap[i]!=null)
                        saveimagetoFile(myBitmap[i],i);
                }

            } catch (IOException e) {

                return null;
            }
            return "successful";
        }
        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            progress_dialog.hide();

        }
    }

如果需要,还可以定义将图像保存到 sd 卡的方法:

void saveimagetoFile(Bitmap bmp,int num){
        try {
            String path = Environment.getExternalStorageDirectory().toString();
            OutputStream fOut = null;
            File file = new File(path, "PriceChecker/pc"+num+".jpg"); // the File to save to
            fOut = new FileOutputStream(file);
            bmp.compress(Bitmap.CompressFormat.JPEG, 100, fOut); //save image to jpeg file
            fOut.flush();
            fOut.close();
        }catch (Exception e){

        }
    }

但在我的情况下,名为 1.jpg 、 2.jpg 、 3.jpg ...等的图像 希望这会有所帮助

编辑: 显示进度对话框的方法:

private void showProgressDialog(){
 AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);

        View promptView;
        LayoutInflater layoutInflater = LayoutInflater.from(OrderActivity_gridstyle.this);
        promptView = layoutInflater.inflate(R.layout.progress_dialog, null);

        alertDialogBuilder.setView(promptView);
        alertDialogBuilder.setCancelable(true);
        progress_dialog=alertDialogBuilder.create();
        progress_dialog.show();}

我使用的进度对话框是形状:轮子,当然你可以使用不同的形状或类型。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:id="@+id/progress_time">

    <ProgressBar
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:id="@+id/prog_circle"
        android:max="100"
        android:progress="0"
        android:indeterminate="true"
        android:indeterminateDrawable="@drawable/progress_wheel"
        android:layout_below="@+id/textView11"
        android:layout_centerHorizontal="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Please Wait"
        android:id="@+id/textView11"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:textColor="@color/blue_" />

</RelativeLayout>

看起来像这样:

【讨论】:

  • 太棒了,这看起来很酷,你更喜欢在哪里更新进度条?
  • 您可以使用 2 种方法:onPreExecute 和 onPostExecute 来显示和隐藏对话框。检查上面的编辑:D
  • 如果您需要以数字或百分比显示进度,请勾选此项:stackoverflow.com/questions/9043683/…
【解决方案2】:

如果您已经开始运行单个下载,那么链接多个图像的下载有什么问题?如果您不关心精确的进度(至少这是我在这里所理解的),您可以简单地通过 for 循环来做到这一点。

伪代码:

String[] urlStack = {"http://www.myimage.com/1.jpg", "http://www.myimage.com/2.jpg", "http://www.myimage.com/3.jpg"};
for(int i = 0; i < urlStack.length; i++)
{
   yourAlreadyDoneDownloadProcedure(updateProgressCallback);
}

... 下载完成后,当然会在下载过程中调用 updateProgressCallback 方法。 ...

private void updateProgressFallback()
{
   progressBarText += 100 / urlStack.length;
}

这只是为了展示您可以/应该如何处理这个问题。


编辑您的第一条评论:

在这种情况下,您应该使用FutureTask

FutureTask 对象可以等待完成,没有任何while()...sleep

例如

for(int i = 0; i < urlStack.length; i++)
{
   // fTask is an array of your download procedure objects

   // get() will wait until the Task is done, no manual sleep commands necessary
   fTask[i].get();

   // since we have a concatenation of downloads, we can update progress here
   progessBarText += 100 / urlStack.length;
}

编辑您的第二条评论:

您将拥有一个实现 Callable 的类,您的所有魔法都发生在这里:

public class MyCallable implements Callable<String>
{
    String url;

    public MyCallable(String s)
    {
        url = s;
    }

    @Override
    public String call() throws Exception
    {
        // Download image here, you have the URL stored in `url`
        return "I'm done";
    }
}

你的 FutureTask 然后运行那个对象:

MyCallable img1 = new MyCallable("http://www.myimage.com/1.jpg");    
MyCallable img2 = new MyCallable("http://www.myimage.com/2.jpg");    
FutureTask<String> fTask = new FutureTask<String>(img1);
fTask.get();
fTask = new FutureTask<String>(img2);
fTask.get();

这是否使它更清晰?上面的代码可以优化很多,这里只是为了了解一下FutureTask需要了解的内容

【讨论】:

  • 完成一个后下载下一张图片,我不想设置for循环,因为它会启动这么多异步任务
  • 那么如何制作未来任务的数组,我认为我们有单个任务,即下载图像,虽然下载图像是多个过程或任务。那么我应该做 asynctask 的未来任务还是在哪里?没看懂,能多解释一下吗
  • 我更新了我的答案,让你了解FutureTask的原理。之后,强烈建议通过将所有 Callables 放入 Array、Vector 等进行优化,然后对其进行迭代。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-10
  • 2012-09-22
  • 1970-01-01
  • 2017-03-11
相关资源
最近更新 更多