“Volley is not suitable for large download or streaming operations, since Volley holds all responses in memory during parsing. For large download operations, consider using an alternative like DownloadManager.”
這是真的,特別是內存小的手機,使用Volley下載很多文件或者單個大文件就不是很恰當了。這裡的large是相對手機內存大小而定。
製作帶進度條的layout
首先準備一個帶Progress Bar的layout
1<!-- res/layout/download.xml -->
2<?xml version="1.0" encoding="utf-8"?>
3<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:app="http://schemas.android.com/apk/res-auto"
5 android:id="@+id/download"
6 android:layout_width="match_parent"
7 android:layout_height="match_parent"
8 tools:context=".MainActivity">
9
10 <LinearLayout
11 android:id="@+id/download"
12 android:layout_width="wrap_content"
13 android:layout_height="wrap_content"
14 android:layout_marginStart="32dp"
15 android:layout_marginEnd="32dp"
16 android:background="@drawable/rounded_edge"
17 android:orientation="vertical"
18 app:layout_constraintBottom_toBottomOf="parent"
19 app:layout_constraintCircleRadius="5dp"
20 app:layout_constraintEnd_toEndOf="parent"
21 app:layout_constraintStart_toStartOf="parent"
22 app:layout_constraintTop_toTopOf="parent">
23
24 <ProgressBar
25 android:id="@+id/progressBar"
26 style="?android:attr/progressBarStyleHorizontal"
27 android:layout_width="80dp"
28 android:layout_height="80dp"
29 android:layout_gravity="center"
30 android:layout_marginTop="16dp"
31 android:background="@drawable/ic_download"
32 android:progressDrawable="@drawable/circular_progress_bar" />
33
34 <TextView
35 android:id="@+id/textView3"
36 android:layout_width="wrap_content"
37 android:layout_height="wrap_content"
38 android:layout_gravity="center"
39 android:layout_marginTop="16dp"
40 android:gravity="center"
41 android:text="@string/download_desc"
42 android:textColor="#fff" />
43
44 <LinearLayout
45 android:layout_width="wrap_content"
46 android:layout_height="wrap_content"
47 android:layout_marginBottom="4dp"
48 android:orientation="horizontal">
49
50 <Button
51 android:id="@+id/dialog_button_agree"
52 android:layout_width="wrap_content"
53 android:layout_height="wrap_content"
54 android:layout_marginStart="16dp"
55 android:layout_weight="1"
56 android:background="@android:color/transparent"
57 android:drawableStart="@drawable/ic_agree"
58 android:text="@string/agree"
59 android:textAlignment="viewStart"
60 android:textColor="#F4E829" />
61
62 <View
63 android:layout_width="1px"
64 android:layout_height="match_parent"
65 android:layout_marginHorizontal="16dp"
66 android:background="@android:color/darker_gray" />
67
68 <Button
69 android:id="@+id/dialog_button_back"
70 android:layout_width="wrap_content"
71 android:layout_height="wrap_content"
72 android:layout_marginEnd="16dp"
73 android:layout_weight="1"
74 android:background="@android:color/transparent"
75 android:drawableStart="@drawable/ic_disagress"
76 android:text="@string/back"
77 android:textAlignment="viewStart"
78 android:textColor="#F4E829" />
79 </LinearLayout>
80
81 </LinearLayout>
82</androidx.constraintlayout.widget.ConstraintLayout>
製作進度條
準備一下進度條。
1<!-- drawable/circular_progress_bar.xml -->
2<?xml version="1.0" encoding="utf-8"?>
3<rotate xmlns:android="http://schemas.android.com/apk/res/android"
4 android:fromDegrees="270"
5 android:toDegrees="270">
6 <shape
7 android:innerRadiusRatio="2.44"
8 android:shape="ring"
9 android:thickness="2dp"
10 android:useLevel="true">
11
12 <gradient
13 android:angle="0"
14 android:endColor="#FFF000"
15 android:startColor="#FFF000"
16 android:type="sweep"
17 android:useLevel="false" />
18 </shape>
19</rotate>
1<!-- drawable/ic_download.xml -->
2<vector xmlns:android="http://schemas.android.com/apk/res/android"
3 android:width="80dp"
4 android:height="80dp"
5 android:viewportWidth="80"
6 android:viewportHeight="80">
7 <path
8 android:fillColor="#686868"
9 android:pathData="M40,7.5163C48.6699,7.5163 56.8366,10.902 62.9673,17.0327C69.098,23.1634 72.4837,31.3301 72.4837,40C72.4837,48.6699 69.098,56.8366 62.9673,62.9673C56.8366,69.098 48.6699,72.4837 40,72.4837C31.3301,72.4837 23.1634,69.098 17.0327,62.9673C10.902,56.8366 7.5163,48.6699 7.5163,40C7.5163,31.3301 10.902,23.1634 17.0327,17.0327C23.1634,10.902 31.3301,7.5163 40,7.5163ZM40,5C20.6699,5 5,20.6699 5,40C5,59.3301 20.6699,75 40,75C59.3301,75 75,59.3301 75,40C75,20.6699 59.3301,5 40,5Z" />
10 <path
11 android:fillColor="#FFF000"
12 android:pathData="M41.0378,49.9393L56.2402,34.4966L54.0244,32.3541L41.5146,45.0422V20H38.4293V45.0422L25.9195,32.3541L23.7037,34.4966L38.9061,49.9393H17V53H63V49.9393H41.0378ZM40.0281,46.6003H39.9719H40.0281Z" />
13</vector>
封裝 Volley
封裝一下 Volley。
1// DownloadRequest.java
2package com.szeching.volleyexample;
3
4import androidx.annotation.Nullable;
5
6import com.android.volley.NetworkResponse;
7import com.android.volley.Request;
8import com.android.volley.Response;
9import com.android.volley.toolbox.HttpHeaderParser;
10
11import java.util.Map;
12
13public class DownloadRequest extends Request<byte[]> {
14
15 private final Response.Listener<byte[]> mListener;
16
17 public Map<String, String> responseHeaders;
18
19 public DownloadRequest(int method, String url, Response.Listener<byte[]> listener, @Nullable Response.ErrorListener errorListener) {
20 super(method, url, errorListener);
21 setShouldCache(false);
22 this.mListener = listener;
23 }
24
25 @Override
26 protected Response<byte[]> parseNetworkResponse(NetworkResponse response) {
27
28 responseHeaders = response.headers;
29 return Response.success(response.data, HttpHeaderParser.parseCacheHeaders(response));
30
31 }
32
33 @Override
34 protected void deliverResponse(byte[] response) {
35 mListener.onResponse(response);
36 }
37
38}
設置進度條
在Activity中發起請求並設置進度條進度。
1// MainActivity.java
2package com.szeching.volleyexample;
3
4import androidx.appcompat.app.AppCompatActivity;
5
6import android.content.Intent;
7import android.net.Uri;
8import android.os.Bundle;
9import android.os.Environment;
10import android.os.Handler;
11import android.widget.ProgressBar;
12
13import androidx.appcompat.app.AppCompatActivity;
14
15import com.android.volley.Request;
16import com.android.volley.RequestQueue;
17import com.android.volley.Response;
18import com.android.volley.VolleyError;
19import com.android.volley.toolbox.HurlStack;
20import com.android.volley.toolbox.Volley;
21
22import java.io.BufferedOutputStream;
23import java.io.ByteArrayInputStream;
24import java.io.File;
25import java.io.FileOutputStream;
26import java.io.IOException;
27import java.io.InputStream;
28import java.util.HashMap;
29
30public class MainActivity extends AppCompatActivity {
31
32 @Override
33 protected void onCreate(Bundle savedInstanceState) {
34 super.onCreate(savedInstanceState);
35 setContentView(R.layout.download);
36 }
37
38 private void requestSource() {
39 request = new DownloadRequest(Request.Method.GET, "https://example.com/example.mp4", new Response.Listener<byte[]>() {
40
41 @Override
42 public void onResponse(byte[] response) {
43 HashMap<String, Object> map = new HashMap<String, Object>();
44 try {
45 if (response != null) {
46 long file_length = response.length;
47 InputStream input = new ByteArrayInputStream(response);
48 File path = getApplicationContext().getExternalFilesDir(Environment.DIRECTORY_MOVIES);
49 File file = new File(path, "filename.mp4");
50 map.put("resume_path", file.toString());
51 BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(file));
52 byte[] data = new byte[1024];
53
54 long total = 0;
55
56 while ((count = input.read(data)) != -1) {
57 total += count;
58 output.write(data, 0, count);
59 int progress = (int) ((int) total * 100 / file_length);
60 Log.d("onProgress",""+progress);
61 progressBar.setProgress(progress);
62 }
63
64 output.flush();
65
66 output.close();
67 input.close();
68 }
69 } catch (Exception e) {
70 e.printStackTrace();
71 }
72 }
73 }, new Response.ErrorListener() {
74 @Override
75 public void onErrorResponse(VolleyError error) {
76 error.printStackTrace();
77 }
78 });
79
80 RequestQueue mRequestQueue = Volley.newRequestQueue(getApplicationContext(), new HurlStack());
81 mRequestQueue.add(request);
82 }
83}