Retrofit解析及文件上傳下載(前后臺(tái)詳細(xì)實(shí)現(xiàn))

在開始之前,本片文章使用得是Rxjava和retrofit結(jié)合啄清,介紹的文件的上傳和下載的實(shí)現(xiàn)六水,如果還不太了解和使用Rxjava和Retrofit的基本使用的同學(xué),可以先了解完這部分內(nèi)容以后,再閱讀本篇文章掷贾。

retrofit的注解字段的介紹和使用:

1.@GET請(qǐng)求的參數(shù)解析:標(biāo)記是GET請(qǐng)求睛榄。
    /**
     * 首頁(yè)Banner
     * http://www.wanandroid.com/banner/json
     * @return BannerResponse
     */
    @GET("/banner/json")
    Observable<DataResponse<List<Banner>>> getHomeBanners();
1.1@query 封裝GET請(qǐng)求參數(shù)的字段
    /**
     * 知識(shí)體系下的文章
     * http://www.wanandroid.com/article/list/json?cid=168
     *
     * @param page page
     * @param cid  cid
     */
    @GET("/article/list/json")
    Observable<DataResponse<Article>> getKnowledgeSystemArticles( @Query("cid") int cid);

1.2 @queryMap 和 @ Query的使用一樣,只是當(dāng)參數(shù)不固定或者參數(shù)比較多的時(shí)候調(diào)用

   @GET("/friend/json")
    Observable<DataResponse<Article>> getFile(@QueryMap Map<String,String> params);

調(diào)用處的代碼:

Map<String,String> options = new HashMap<String,String>();
options.put("name",trainName);
options.put("key",KEY);
Call<Movie> movie = service.getFile(options);

1.3 @Path:url中的占位符,相當(dāng)于動(dòng)態(tài)的改變url, 當(dāng)然別掉了{(lán)}將動(dòng)態(tài)的配置參數(shù)包起來.


    /**
     * 搜索
     * http://www.wanandroid.com/article/query/0/json
     *
     * @param page page
     * @param k    POST search key
     */
    @POST("/article/query/{page}/json")
    @FormUrlEncoded
    Observable<DataResponse<Article>> getSearchArticles(@Path("page") int page, @Field("k") String k);

2.@POST請(qǐng)求的參數(shù)解析

2.1@FormUrlEncoded

在post請(qǐng)求中配置該參數(shù)想帅,說明該請(qǐng)求將表單的形式傳遞參數(shù)场靴,它不能用于get請(qǐng)求。
@FormUrlEncoded將會(huì)自動(dòng)將請(qǐng)求參數(shù)的類型調(diào)整為application/x-www-form-urlencoded港准,假如content傳遞的參數(shù)為Good Luck旨剥,那么最后得到的請(qǐng)求體就是

content=Good+Luck
FormUrlEncoded不能用于Get請(qǐng)求

2.2 @Field標(biāo)記POST請(qǐng)求中,鍵值對(duì)參數(shù)的key,例:username叉趣,和password泞边,當(dāng)調(diào)用的loing()方法時(shí),自動(dòng)封裝到請(qǐng)求參數(shù)中

@Field注解將每一個(gè)請(qǐng)求參數(shù)都存放至請(qǐng)求體中疗杉,還可以添加encoded參數(shù)阵谚,該參數(shù)為boolean型,具體的用法為

@Field(value = "book", encoded = true) String book

encoded參數(shù)為true的話烟具,key-value-pair將會(huì)被編碼梢什,即將中文和特殊字符進(jìn)行編碼轉(zhuǎn)換

    /**
     * 登錄
     *
     * @param username username
     * @param password password
     * @return Deferred<User>
     */
    @POST("/user/login")
    @FormUrlEncoded
    Observable<DataResponse<User>> login(@Field("username") String username, @Field("password") String password);

2.3 @FiledMap:這個(gè)跟Field差不多,將所有的參數(shù)用Map的方式進(jìn)行傳遞

@FormUrlEncoded
@POST("voice")
Call<Vioce> sendVoiceMessage(@FieldMap Map<String,String> options);

調(diào)用處的代碼:

Map<String,String> options = new HashMap<String,String>();
options.put("valicode","123456");
options.put("to","18772351259");
options.put("key",voice_KEY);
Call<Vioce> voice = service.sendVoiceMessage(options);

2.4 @Body :將所有的參數(shù)封住到一個(gè)自定義的對(duì)象,如果參數(shù)過多朝聋,統(tǒng)一封裝到類中應(yīng)該會(huì)更好嗡午,便于維護(hù)代碼。

@FormUrlEncoded
@POST("voice")
Call<Vioce> sendVoiceMessage(@Body AddParams params);

public class AddParams{
    String valicode;
    String to;
    String key;

    public void setKey(String key) {
        this.key = key;
    }

    public void setTo(String to) {
        this.to = to;
    }

    public void setValicode(String valicode) {
        this.valicode = valicode;
    }

3冀痕、(單荔睹、多)文件上傳實(shí)現(xiàn)及參數(shù)解析

3.1 @Part:配合@Multipart用于文件上傳

在介紹文件上傳之前,為了一些比較喜歡騷動(dòng)的同學(xué)言蛇,我也貼出java后臺(tái)的接受代碼僻他,方便我們更好的理解文件上傳的詳細(xì)過程。也方便后面的介紹腊尚。但是這個(gè)Servlet需要借助2個(gè)jar包吨拗。


lib.png
public class UploadFileServlet extends HttpServlet {

    
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.getWriter().write("this is the post request! ");
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)  
            throws ServletException, IOException {  
      response.setContentType("text/html");  
      PrintWriter out = response.getWriter();  

      // 創(chuàng)建文件項(xiàng)目工廠對(duì)象  
      DiskFileItemFactory factory = new DiskFileItemFactory();  

      // 設(shè)置文件上傳路徑  
      String upload = "f:";  
      // 獲取系統(tǒng)默認(rèn)的臨時(shí)文件保存路徑,該路徑為Tomcat根目錄下的temp文件夾  
      String temp = System.getProperty("java.io.tmpdir");  
      // 設(shè)置緩沖區(qū)大小為 5M  
      factory.setSizeThreshold(1024 * 1024 * 5);  
      // 設(shè)置臨時(shí)文件夾為temp  
      factory.setRepository(new File(temp));  
      // 用工廠實(shí)例化上傳組件,ServletFileUpload 用來解析文件上傳請(qǐng)求  
      ServletFileUpload servletFileUpload = new ServletFileUpload(factory);  

      // 解析結(jié)果放在List中  
      try {  
          List<FileItem> list = servletFileUpload.parseRequest(request);  

          for (FileItem item : list) {  
              String name = item.getFieldName();  
              InputStream is = item.getInputStream();  

              System.out.println("the current name is " + name);  

              if (name.contains("photo") ||name.contains("file")) {  
                  try {  
                      inputStream2File(is,  
                            upload + "\\" + System.currentTimeMillis()  
                                    + item.getName());  
                  } catch (Exception e) {  
                      e.printStackTrace();  
                  }  
              } else {  
                  String key = item.getName();  
                  String value = item.getString(); 
//                  System.out.println(value );
//                  System.out.println(key + "---" + value);  
              }  
          }  

          out.write("success");  
      } catch (FileUploadException e) {  
          e.printStackTrace();  
          out.write("failure");  
      }  

      out.flush();  
      out.close();  

  }  

  // 流轉(zhuǎn)化成字符串  
  public static String inputStream2String(InputStream is) throws IOException {  
      ByteArrayOutputStream baos = new ByteArrayOutputStream();  
      int i = -1;  
      while ((i = is.read()) != -1) {  
          baos.write(i);  
      }  
      return baos.toString();  
  }  

  // 流轉(zhuǎn)化成文件  
  public static void inputStream2File(InputStream is, String savePath)  
          throws Exception {  
      System.out.println("the file path is  :" + savePath);  
      File file = new File(savePath);  
      InputStream inputSteam = is;  
      BufferedInputStream fis = new BufferedInputStream(inputSteam);  
      FileOutputStream fos = new FileOutputStream(file);  
      int f;  
      while ((f = fis.read()) != -1) {  
          fos.write(f);  
      }  
      fos.flush();  
      fos.close();  
      fis.close();  
      inputSteam.close();  
  }  
}

    @Multipart
    @POST("UploadServlet")
    Call<ResponseBody> upLoadPrefectFile( @Part("description") RequestBody description,@Part MultipartBody.Part file);

在Activity中的代碼:

        final RequestBody requestBody = createPartFromString("this is des!");
        retrofit2.Call call = RetrofitHelper.getUpLoadFileAPI().upLoadPrefectFile(requestBody, prepareFilePart(new File("/sdcard/1.zip"), "file"));
        call.enqueue(new retrofit2.Callback() {
            @Override
            public void onResponse(retrofit2.Call call, retrofit2.Response response) {

                String s = response.body().toString();
                String s1 = response.message().toString();
                Log.d("TAG", "onResponse: " + s1);
                Toast.makeText(TestUploadFileActivity.this, "上傳成功!" + s, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onFailure(retrofit2.Call call, Throwable t) {

                String s = t.getMessage().toString();
                Log.d(TAG, s);
                Toast.makeText(TestUploadFileActivity.this, "上傳失敗!" + s, Toast.LENGTH_SHORT).show();
            }
        });

在上面的代碼中出現(xiàn)了婿斥,我們也貼出該方法的代碼:

   @NonNull
    private MultipartBody.Part prepareFilePart(File file, String partName) {

        // 為file建立RequestBody實(shí)例
        RequestBody requestFile =
                RequestBody.create(MediaType.parse(MULTIPART_FORM_DATA), file);

        // MultipartBody.Part借助文件名完成最終的上傳
        return MultipartBody.Part.createFormData(partName, file.getName(), requestFile);
    }

這里解釋一下 MultipartBody.Part.createFormData()方法的使用和參數(shù)說明劝篷。第一個(gè)參數(shù)partName為與后臺(tái)協(xié)調(diào)的進(jìn)行文件檢索的名稱,也可以這樣理解民宿,如果是txt文件娇妓,我們標(biāo)記為txt,如果是照片,標(biāo)記為jpg活鹰,其他文件標(biāo)記為file,方便后臺(tái)管理和存儲(chǔ)文件哈恰。
我們?cè)诳纯磒artName在后臺(tái)是如何進(jìn)行區(qū)分和使用的坟桅?


image.png

根據(jù)檢索出不同的文件類型,進(jìn)行不同的操作蕊蝗。

3.1.1了解 multipart/form-data

我們這里這是簡(jiǎn)單的介紹一下:
RequestBody requestFile =
RequestBody.create(MediaType.parse("multipart/form-data"), file);

這里在看看我們構(gòu)建RequestBody的代碼:這里參數(shù)至于為什么使用MediaType.parse("multipart/form-data"),需要我們了解http的傳輸協(xié)議:

在最初的http協(xié)議中赖舟,沒有定義上傳文件的Method蓬戚,為了實(shí)現(xiàn)這個(gè)功能,http協(xié)議組改造了post請(qǐng)求宾抓,添加了一種post規(guī)范子漩,設(shè)定這種規(guī)范的Content-Type為multipart/form-data;boundary=bound,其中{bound}是定義的分隔符,用于分割各項(xiàng)內(nèi)容(文件,key-value對(duì))石洗,不然服務(wù)器無法正確識(shí)別各項(xiàng)內(nèi)容幢泼。post body里需要用到,盡量保證隨機(jī)唯一。

3.1.2 post格式如下:
–${bound} 
Content-Disposition: form-data; name=”Filename”

HTTP.pdf 
–${bound} 
Content-Disposition: form-data; name=”file000”; filename=”HTTP協(xié)議詳解.pdf” 
Content-Type: application/octet-stream

%PDF-1.5 
file content 
%%EOF

–${bound} 
Content-Disposition: form-data; name=”Upload”

Submit Query 
–${bound}–
${bound}是Content-Type里boundary的值
3.1.3 Retrofit2 對(duì)multipart/form-data的封裝

Retrofit其實(shí)是個(gè)網(wǎng)絡(luò)代理框架讲衫,負(fù)責(zé)封裝請(qǐng)求缕棵,然后把請(qǐng)求分發(fā)給http協(xié)議具體實(shí)現(xiàn)者-httpclient。retrofit默認(rèn)的httpclient是okhttp涉兽。

既然Retrofit不實(shí)現(xiàn)http招驴,為啥還用它呢。因?yàn)樗奖悖枷畏。?br> Retrofit會(huì)根據(jù)注解封裝網(wǎng)絡(luò)請(qǐng)求别厘,待httpclient請(qǐng)求完成后,把原始response內(nèi)容通過轉(zhuǎn)化器(converter)轉(zhuǎn)化成我們需要的對(duì)象(object)拥诡。

具體怎么使用 retrofit2,請(qǐng)參考: Retrofit2官網(wǎng)

那么Retrofit和okhttp怎么封裝這些multipart/form-data上傳數(shù)據(jù)呢

在retrofit中:
@retrofit2.http.Multipart: 標(biāo)記一個(gè)請(qǐng)求是multipart/form-data類型,需要和@retrofit2.http.POST一同使用触趴,并且方法參數(shù)必須是@retrofit2.http.Part注解。
@retrofit2.http.Part: 代表Multipart里的一項(xiàng)數(shù)據(jù),即用${bound}分隔的內(nèi)容塊渴肉。
在okhttp3中:
okhttp3.MultipartBody: multipart/form-data的抽象封裝,繼承okhttp3.RequestBody
okhttp3.MultipartBody.Part: multipart/form-data里的一項(xiàng)數(shù)據(jù)冗懦。

以上內(nèi)容摘自 一葉扁舟的博客

3.2 多文件上傳:(2種方式:)

3.2.1 第一種是方式:文件個(gè)數(shù)固定
    @Multipart
    @POST("UploadServlet")
    Call<ResponseBody> uploadMultipleFiles(
            @Part("description") RequestBody description,
            @Part MultipartBody.Part file1,
            @Part MultipartBody.Part file2);
3.2.2 第二種是方式:文件個(gè)數(shù)不固定
    @Multipart
    @POST("UploadServlet")
    Call<ResponseBody> uploadMapFile(@PartMap Map<String, RequestBody> params);

這里我們只展示文件個(gè)數(shù)不固定的上傳方法的使用:

        File file=new File("/sdcard/img.jpg");
        File file1=new File("/sdcard/ic.jpg");
        File file2=new File("/sdcard/1.txt");

        RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
        RequestBody requestBody1 = RequestBody.create(MediaType.parse("multipart/form-data"), file1);
        RequestBody requestBody2 = RequestBody.create(MediaType.parse("multipart/form-data"), file2);

        Map<String, RequestBody> params=new HashMap<>() ;
        params.put("file\"; filename=\""+ file.getName(), requestBody);
        params.put("file\"; filename=\""+ file1.getName(), requestBody1);
        params.put("file\"; filename=\""+ file2.getName(), requestBody2);

        retrofit2.Call call = RetrofitHelper.getUpLoadFileAPI().uploadMapFile(params);
        call.enqueue(new retrofit2.Callback() {
            @Override
            public void onResponse(retrofit2.Call call, retrofit2.Response response) {
                Toast.makeText(TestUploadFileActivity.this, "上傳成功!", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onFailure(retrofit2.Call call, Throwable t) {
                Log.d("Tag",t.getMessage().toString());
                Toast.makeText(TestUploadFileActivity.this, "上傳失敗!", Toast.LENGTH_SHORT).show();
            }
        });

4、文件的下載

我們都實(shí)現(xiàn)了文件的上傳了宾娜,還不能堅(jiān)持一下批狐,把文件下載搞定?那必須的必扒八嚣艇!下載文件其實(shí)就一個(gè)普通的GET 請(qǐng)求,只不過我們處理好IO操作华弓,將response.body()進(jìn)行保存為自己想要的位置或者處理食零。

    @GET("u=107188706,3427188039&fm=27&gp=0.jpg")
    Call<ResponseBody> downloadFile();

Activity中的使用:

                Call<ResponseBody> call = RetrofitHelper.getDownloadApi().downloadFile();
                call.enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                        boolean writtenToDisk = writeResponseBodyToDisk(response.body());

                        btnDownload.setText(writtenToDisk ? "success" : "false");
                    }

                    @Override
                    public void onFailure(Call<ResponseBody> call, Throwable t) {
                        Toast.makeText(TestUploadFileActivity.this, "fail", Toast.LENGTH_SHORT).show();
                    }
                });

writeResponseBodyToDisk()方法的具體實(shí)現(xiàn):

 private boolean writeResponseBodyToDisk(ResponseBody body) {
        try {
            // todo change the file location/name according to your needs
            File futureStudioIconFile = new File(Environment.getExternalStorageDirectory() + File.separator + "taylor.png");

            Log.d(TAG, "writeResponseBodyToDisk: " + Environment.getExternalStorageDirectory().getAbsolutePath());

            InputStream inputStream = null;
            OutputStream outputStream = null;

            try {
                byte[] fileReader = new byte[4096];

                long fileSize = body.contentLength();
                long fileSizeDownloaded = 0;

                inputStream = body.byteStream();
                outputStream = new FileOutputStream(futureStudioIconFile);

                while (true) {
                    int read = inputStream.read(fileReader);

                    if (read == -1) {
                        break;
                    }

                    outputStream.write(fileReader, 0, read);

                    fileSizeDownloaded += read;

                    Log.d(TAG, "file download: " + fileSizeDownloaded + " of " + fileSize);
                }

                outputStream.flush();

                return true;
            } catch (IOException e) {
                return false;
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }

                if (outputStream != null) {
                    outputStream.close();
                }
            }
        } catch (IOException e) {
            return false;
        }
    }

5、其他細(xì)節(jié)問題總結(jié)

5.1 @Header:添加http header
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization);

等同于:

@Headers("Authorization: authorization")//這里authorization就是上面方法里傳進(jìn)來變量的值
@GET("widget/list")
Call<User> getUser()
5.2為某個(gè)請(qǐng)求設(shè)置完整的URL

? 假如說你的某一個(gè)請(qǐng)求不是以baseUrl開頭該怎么辦呢寂屏?別著急贰谣,辦法很簡(jiǎn)單娜搂,看下面這個(gè)例子你就懂了


public interface BlueService {  
    @GET
    public Call<ResponseBody> profilePicture(@Url String url);
}

Retrofit retrofit = Retrofit.Builder()  
    .baseUrl("https://your.api.url/");
    .build();

BlueService service = retrofit.create(BlueService.class);  
service.profilePicture("https://s3.amazon.com/profile-picture/path");

還有一些添加Header的具體的用法:
Header

Retrofit下載上傳文件自定義進(jìn)度實(shí)現(xiàn)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市吱抚,隨后出現(xiàn)的幾起案子百宇,更是在濱河造成了極大的恐慌,老刑警劉巖秘豹,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件携御,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡既绕,警方通過查閱死者的電腦和手機(jī)啄刹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凄贩,“玉大人誓军,你說我怎么就攤上這事∑T” “怎么了昵时?”我有些...
    開封第一講書人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)评肆。 經(jīng)常有香客問我债查,道長(zhǎng),這世上最難降的妖魔是什么瓜挽? 我笑而不...
    開封第一講書人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任盹廷,我火速辦了婚禮,結(jié)果婚禮上久橙,老公的妹妹穿的比我還像新娘俄占。我一直安慰自己,他們只是感情好淆衷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開白布缸榄。 她就那樣靜靜地躺著,像睡著了一般祝拯。 火紅的嫁衣襯著肌膚如雪甚带。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,231評(píng)論 1 299
  • 那天佳头,我揣著相機(jī)與錄音鹰贵,去河邊找鬼。 笑死康嘉,一個(gè)胖子當(dāng)著我的面吹牛碉输,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播亭珍,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼敷钾,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼枝哄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起阻荒,我...
    開封第一講書人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤挠锥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后侨赡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瘪贱,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年辆毡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片甜害。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡舶掖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出尔店,到底是詐尸還是另有隱情眨攘,我是刑警寧澤,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布嚣州,位于F島的核電站鲫售,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏该肴。R本人自食惡果不足惜情竹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一夏伊、第九天 我趴在偏房一處隱蔽的房頂上張望挽牢。 院中可真熱鬧腔丧,春花似錦倾贰、人聲如沸垄懂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)勋拟。三九已至法梯,卻和暖如春苔货,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背立哑。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工夜惭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人刁憋。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓滥嘴,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親至耻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子若皱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 整體Retrofit內(nèi)容如下: 1镊叁、Retrofit解析1之前哨站——理解RESTful2、Retrofit解析2...
    隔壁老李頭閱讀 15,076評(píng)論 4 39
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,085評(píng)論 25 707
  • 轉(zhuǎn)載自:陳開華博客 Retrofit2是目前很流行的android網(wǎng)絡(luò)框架走触,運(yùn)用注解和動(dòng)態(tài)代理晦譬,極大的簡(jiǎn)化了網(wǎng)絡(luò)請(qǐng)...
    EitanLiu閱讀 13,693評(píng)論 8 44
  • 一、簡(jiǎn)介 Retrofit是Square公司開發(fā)的一款針對(duì)Android網(wǎng)絡(luò)請(qǐng)求的框架互广,Retrofit2底層基于...
    Devil不加V閱讀 547評(píng)論 0 0
  • 燈光暗淡敛腌,夜晚璀璨,走在繁華的大街小巷惫皱,十字路口人來人往像樊,低頭尋不見影子,抬頭分不清日月旅敷,天黑天明生棍,我們這...
    素衣念慈閱讀 260評(píng)論 0 2