ติดตั้งเพิ่มเติม+rxjava เป็นเฟรมเวิร์กเครือข่ายที่สำคัญที่สุดในตลาด มันใช้งานง่ายมากในการทำคำขอเครือข่ายธรรมดา ฉันใช้ชุดเพิ่มเติมเพื่ออัปโหลดไฟล์และดาวน์โหลดไฟล์มาก่อน แต่ฉันพบว่าการใช้ชุดเพิ่มเติมเพื่อดาวน์โหลดไม่รองรับความคืบหน้าการโทรกลับตามค่าเริ่มต้น แต่ผลิตภัณฑ์ต้องการให้ความคืบหน้าการดาวน์โหลดปรากฏขึ้นเมื่อดาวน์โหลดไฟล์ดังนั้นฉันต้องเข้าไป
ถัดไปให้ห่อหุ้มมันเข้าด้วยกันและใช้ RETROFIT+RXJAVA เพื่อดาวน์โหลดไฟล์พร้อมความคืบหน้า
GitHub: jsdownload
มาดูแผนภาพ UML ก่อน:
คุณอาจไม่แน่ใจว่าจะจัดการกับมันได้อย่างไร ไม่ต้องกังวลลองทีละขั้นตอน:
1. จำเป็นต้องเพิ่มการพึ่งพาอาศัยกัน
คอมไพล์ 'io.reactivex: rxjava: 1.1.0'compile' io.reactivex: rxandroid: 1.1.0'compile 'com.squareup.retrofit2: Retrofit: 2.0.0-beta4'compile' com.squareup.retrofit 'com.squareup.retrofit2: Converter-Gson: 2.0.0-beta4'compile' com.squareup.retrofit2: Adapter-Rxjava: 2.0.0-beta4 '
ให้ความสนใจกับหมายเลขเวอร์ชันเมื่อใช้งาน
2. เขียนการโทรกลับ
/*** คำอธิบาย: ดาวน์โหลดความคืบหน้าการโทรกลับ* สร้างโดย JIA เมื่อ 2017/11/30 * เหตุผลที่ผู้คนสามารถทำได้เพราะพวกเขาเชื่อว่าพวกเขาสามารถ*/ส่วนต่อประสานสาธารณะ jsdownloadListener {void onstartdownload (); เป็นโมฆะ onprogress (ความคืบหน้า int); เป็นโมฆะ OnfinishDownload (); เป็นโมฆะ onfail (String errorInfo);}ไม่จำเป็นต้องบอกว่าการโทรกลับอย่างน้อยควรมีวิธีการโทรกลับสี่วิธี: เริ่มดาวน์โหลด, ดาวน์โหลดความคืบหน้า, ดาวน์โหลดเสร็จสมบูรณ์และดาวน์โหลดความล้มเหลว
โปรดทราบว่าเปอร์เซ็นต์ความคืบหน้าจะถูกส่งกลับในวิธีการพัฒนาและเหตุผลความล้มเหลวจะถูกส่งคืนใน onfail
3. เขียน ResponseBody ใหม่และคำนวณเปอร์เซ็นต์การดาวน์โหลด
/*** คำอธิบาย: ดาวน์โหลดตัวตนที่มีความคืบหน้า* สร้างโดย JIA เมื่อ 2017/11/30 * เหตุผลที่ผู้คนสามารถทำได้คือพวกเขาเชื่อว่าพวกเขาสามารถ*/ชั้นเรียนสาธารณะ jsresponsebody ขยายการตอบสนอง {private responsebody responsebody; private jsdownloadlistener downloadlistener; // bufferedSource เป็นสตรีมอินพุตในไลบรารี OKIO ซึ่งใช้ที่นี่เป็นอินพุตสตรีม BufferedSource ส่วนตัว BufferedSource; สาธารณะ jsResponseBody (ResponseBody ResponseBody, JSDOWLOADLISTENER DOWNWALLLISTENER) {this.ResponseBody = ResponseBody; this.downloadListener = downloadListener; } @Override Public MediaType ContentType () {return ResponceBody.ContentType (); } @Override Public Long ContentLength () {return ResponceBody.ContentLength (); } @Override Public BufferedSource Source () {ถ้า (bufferedSource == null) {bufferedSource = okio.buffer (แหล่งที่มา (ResponceBody.source ())); } return bufferedSource; } แหล่งที่มาส่วนตัว (แหล่งที่มา) {ส่งคืนใหม่ forwardingSource (แหล่งที่มา) {long totalByTesread = 0l; @Override สาธารณะอ่านยาว (บัฟเฟอร์อ่างล้างจานยาว bytecount) พ่น IOException {long bytesRead = super.read (sink, bytecount); // read () ส่งคืนจำนวนไบต์ที่อ่านหรือ -1 ถ้าแหล่งที่มานี้หมด TotalByTesRead += bytesRead! = -1? BytesRead: 0; log.e ("ดาวน์โหลด", "อ่าน:"+ (int) (TotalByTesRead * 100 / ResponseBody.ContentLength ())); if (null! = downloadListener) {if (bytesRead! = -1) {downloadListener.onProgress ((int) (TotalByTesRead * 100 / Response.ContentLength ()); }} return bytesRead; - -ผ่าน Responsebody และ JsdownloadListener สำหรับคำขอเครือข่ายในโครงสร้าง
แกนกลางนี่คือ วิธีต้นฉบับซึ่งส่งคืนวัตถุ ForwardingSource ซึ่งเราแทนที่วิธีการอ่านคำนวณเปอร์เซ็นต์ในวิธีการอ่านและส่งผ่านไปยังการโทรกลับ downloadListener
4. interceptor
ไม่เพียงพอที่จะห่อหุ้ม ResponseBody เท่านั้น กุญแจสำคัญคือเราต้องได้รับ Responsebody ที่ร้องขอที่นี่เราใช้ interceptor
/*** คำอธิบาย: ดาวน์โหลด interceptor พร้อมความคืบหน้า* สร้างโดย JIA เมื่อ 2017/11/30 * เหตุผลที่ผู้คนสามารถทำได้คือพวกเขาเชื่อว่าพวกเขาสามารถ*/คลาสสาธารณะ JsdownloadInterceptor ใช้ interceptor {ส่วนตัว jsdownloadlistener ดาวน์โหลด listener; สาธารณะ jsdownloadInterceptor (jsdownloadListener downloadListener) {this.downloadListener = downloadListener; } @Override สกัดกั้นการตอบสนองสาธารณะ (ห่วงโซ่โซ่) โยน ioException {ตอบสนองการตอบสนอง = chain.proceed (chain.request ()); return response.newbuilder (). ร่างกาย (ใหม่ jsresponsebody (response.body (), downloadListener)). build (); -โดยปกติแล้วตัวดักถูกใช้เพื่อเพิ่มลบหรือแปลงข้อมูลการร้องขอหรือการตอบกลับ
ส่งคืน ResponseBody ที่เราเพิ่งห่อหุ้มในการสกัดกั้นวิธีการสกัดกั้น
5. บริการขอเครือข่าย
/** * คำอธิบาย: * สร้างโดย JIA เมื่อ 2017/11/30 * เหตุผลที่ผู้คนสามารถทำได้คือเพราะพวกเขาเชื่อว่าพวกเขาสามารถ*/อินเทอร์เฟซสาธารณะดาวน์โหลด Service {@streaming @get สังเกตได้สังเกต:
ที่นี่ @url คือการผ่าน URL ดาวน์โหลดที่สมบูรณ์; คุณไม่จำเป็นต้องสกัดกั้นวิธีการอธิบายประกอบ @streaming
6. การร้องขอขั้นสุดท้ายเริ่มต้นขึ้น
/** 1. คำอธิบาย: ดาวน์โหลดคลาสเครื่องมือ 2. สร้างโดย JIA เมื่อ 2017/11/30 3. เหตุผลที่ผู้คนสามารถทำได้คือพวกเขาเชื่อว่าพวกเขาสามารถ*/คลาสสาธารณะดาวน์โหลด {private static สตริงสุดท้ายคงที่ = "downloadUtils"; int คงสุดท้ายคงที่ int default_timeout = 15; ติดตั้งเพิ่มเติมส่วนตัว ผู้ฟังส่วนตัว JSDOWLLOADLISTENER; สตริงส่วนตัว baseurl; Downloadurl สตริงส่วนตัว; Public DownloadUtils (String BaseUrl, JSDownloadListener Listener) {this.baseurl = baseUrl; this.listener = ผู้ฟัง; jsdownloadInterceptor minterceptor = new JSDownloadInterceptor (ผู้ฟัง); okhttpClient httpClient = new okhttpClient.builder () .AdDinterceptor (minterceptor) .ReterOnConnectionFailure (จริง) .connectTimeOut (default_timeout, timeUnit.seconds) .build (); retrofit = ใหม่ retrofit.builder () .baseurl (baseUrl) .client (httpClient) .addcalladapterfactory (rxjavacalladapterfactory.create ()) .build (); } / ** * เริ่มดาวน์โหลด * * @param url * @param filepath * @param สมาชิก * / โมฆะสาธารณะดาวน์โหลด (@nonnull string url, สตริง filepath สุดท้าย, สมาชิกสมาชิก) {listener.onstartdownload (); // subcribeon () เปลี่ยนเธรดของรหัสก่อนที่จะเรียกว่า // observeon () เปลี่ยนเธรดของรหัสหลังจากที่เรียกว่า retrofit.create (downloadservice.class) .download (url) .subscribeonon (schedulers.io () CALL (ResponseBody ResponseBody) {return ResponceBody.ByTestream ();}}) .Observeon (schedulers.Computation ()) // ใช้ในการคำนวณงาน doonnext (action1 <putstream> () {@Override public Call .Observeon (Androidschedulers.MainThread ()) .subscribe (สมาชิก); } / ** * เขียนสตรีมอินพุตไปยังไฟล์ * * @param inputString * @param filepath * / private void writefile (inputStream inputString, สตริง filePath) {ไฟล์ไฟล์ = ไฟล์ใหม่ (filePath); if (file.exists ()) {file.delete (); } fileOutputStream fos = null; ลอง {fos = ใหม่ fileOutputStream (ไฟล์); ไบต์ [] b = ไบต์ใหม่ [1024]; int len; ในขณะที่ ((len = inputString.read (b))! = -1) {fos.write (b, 0, len); } inputString.close (); fos.close (); } catch (filenotfoundexception e) {listener.onfail ("filenotfoundexception"); } catch (ioexception e) {listener.onfail ("ioexception"); -แน่นอนคุณต้องให้ความสนใจกับแต่ละสถานที่ของการโทรกลับ
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น