HTTP Retrofit 網絡傳輸

原文:https://www.jianshu.com/p/0fda3132cf98java

Retrofit註解

  • 請求方法
註解代碼 請求格式
@GET GET請求
@POST POST請求
@DELETE DELETE請求
@HEAD HEAD請求
@OPTIONS OPTIONS請求
@PATCH PATCH請求
  • 請求參數
註解代碼 說明
@Headers 添加請求頭
@Path 替換路徑
@Query 替代參數值,一般是結合get請求的
@FormUrlEncoded 用表單數據提交
@Field 替換參數值,是結合post請求的

前提:react

Android 系統上面默認全部Http的請求都被阻止了。android

須要在androidmanifest.xml的 application標籤上加入 android:usesCleartextTraffic="true"web

首先引入依賴:Gson能夠將Json和基本數據類型之間作轉換;Okhtttp用來進行HTTP鏈接(Retrofit就是創建在OkHttp之上的);ReJava用來提供一個異步處理的操做。json

//Gson庫
implementation 'com.google.code.gson:gson:2.8.2'
// Okhttp庫
implementation 'com.squareup.okhttp3:okhttp:3.1.2'
// Retrofit庫
implementation 'com.squareup.retrofit2:retrofit:2.0.2'
implementation 'com.squareup.retrofit2:converter-gson:2.0.2'  //gson轉化
implementation 'com.squareup.retrofit2:adapter-rxjava:2.0.2'  //RxJava
//RxJava庫
implementation 'io.reactivex:rxandroid:1.0.1'

先看下服務端代碼,其實就是接收到了鏈接後返回一個JSON格式的數據:服務器

var http = require('http');
var url = require('url');
var util = require('util');
 
http.createServer(function(req, res){
    res.writeHead(200, {'Content-Type': 'text/plain'});
    // 解析 url 參數
    var params = url.parse(req.url, true).query;
    console.log("有鏈接");
    console.log(util.inspect(url.parse(req.url, true)));
    //發送JSON數據
    var jsonobj = {time:0, code:1, data:{song_url:'yangzhilong_tem.mp3', msg:123}};
    res.end(JSON.stringify(jsonobj));
}).listen(3000);

先定義一個Bean來表示從服務端獲取到的東西:網絡

import java.util.Map;
public class User {
    private long time;
    private int code;
    private Map<String, String> data;

    public Map<String, String> getData() {
        return data;
    }
    public int getCode() {
        return code;
    }
    public long getTime() {
        return time;
    }
}

定義一個接口來提供服務:app

import retrofit2.http.GET;
import retrofit2.http.Query;
import rx.Observable;
public interface GetAPI {
    //設置路徑    
    @GET("create/original")
    Observable<User> getUser(@Query("author_id") String author_id, @Query("type") String type, @Query("info") String info);
}

java代碼:異步

package com.example.m_evolution;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import com.example.m_evolution.Bean.User;
import com.example.m_evolution.HttpAPI.GetAPI;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

public class TestActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);

        OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(10, TimeUnit.SECONDS)
            .build();

        Retrofit retrofit = new Retrofit.Builder()
            //設置數據解析器
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            //設置網絡請求的Url地址
            .baseUrl("http://172.17.1.96:3000/")
            .client(okHttpClient)
            .build();

        // 建立網絡請求接口的實例
        GetAPI mApi = retrofit.create(GetAPI.class);

        mApi.getUser("1", "10", "[嘻哈,興奮]")
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<User>() {
                @Override
                public void onCompleted() {
                    Log.d("TestActivity", "調用完成");
                }

                @Override
                public void onError(Throwable e) {
                    Log.d("TestActivity", "請求失敗"+e.toString());
                }

                @Override
                public void onNext(User user) {
                    Log.d("TestActivity", "請求成功");
                    Log.d("TestActivity", "time:"+user.getTime());
                    Log.d("TestActivity", "code:"+user.getCode());
                    Log.d("TestActivity", "song_url:"+user.getData().get("song_url")+"; msg:"+user.getData().get("msg"));
                }
            });
    }
}

客戶端結果:ide

服務端結果:

 

 GET請求:

服務端提供的接口:

客戶端:

    //獲取某用戶的信息
    @GET("/user/info")
    Observable<UserInfoHTTPResult> get_user_info(@Header("Authorization")String token, @Query("user_id")String user_id);
public class UserInfoHTTPResult {
    private long time;  //服務器響應時間
    private int code;  //響應碼 0表示正常
    private String msg;  //錯誤信息
    private Map<String, String> data;

    public long getTime() {
        return time;
    }
    public int getCode() {
        return code;
    }
    public String getMsg() {
        return msg;
    }
    public String getUserName(){
        return data.get("username");
    }
    public String getGender(){
        return data.get("gender");
    }
    public String getAvatarUrl(){
        return data.get("avatar");
    }
}
httpAPI.get_user_info(MyApp.token_pre+myApp.getUser_token(), user_id)
                    .subscribeOn(Schedulers.newThread())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Subscriber<UserInfoHTTPResult>() {
                        @Override
                        public void onCompleted() {
                            Log.d(TAG, "onCompleted: "+"調用完成");
                        }

                        @Override
                        public void onError(Throwable e) {
                            Log.d(TAG, "onError: "+"請求失敗: "+e.toString());
                            myApp.MakeToast("網絡出錯");
                        }

                        @Override
                        public void onNext(UserInfoHTTPResult userInfoHTTPResult) {
                            if(userInfoHTTPResult.getCode()==0){
                                //更新我的信息
                                myApp.setUser_nickname(userInfoHTTPResult.getUserName());
                                myApp.setUser_gender(userInfoHTTPResult.getGender());
                                myApp.setUser_head_url(userInfoHTTPResult.getAvatarUrl());
                                Log.d(TAG, "onNext: username: "+myApp.getUser_nickname());
                                Log.d(TAG, "onNext: gender: "+myApp.getUser_gender());
                                Log.d(TAG, "onNext: avatar: "+myApp.getUser_head_url());
                                editor.putString("user_nickname",myApp.getUser_nickname());
                                editor.putString("user_gender",myApp.getUser_gender());
                                editor.putString("user_head_url", myApp.getUser_head_url());
                                editor.commit();
                                //修改控件
                                tv_user_nickname.setText(userInfoHTTPResult.getUserName());
                                if(myApp.getUser_gender().equals("female")){
                                    iv_user_gender.setImageResource(R.drawable.icon_user_gender_female);
                                }
                                else{
                                    iv_user_gender.setImageResource(R.drawable.icon_user_gender_male);
                                }
                                ImageLoader.getInstance().displayImage(MyApp.baseUrl+myApp.getUser_head_url(),iv_user_head);
                            }
                        }
                    });

 

 POST請求:

服務端提供的接口:

注意,最後一個參數avatar表示頭像,涉及到文件的上傳;

    //用戶更新信息
    @Multipart
    @POST("/update/user")
    Observable<UpdateUserHTTPResult> update_user(@Header("Authorization")String token, @Part("user_id") RequestBody user_id, @Part("username")RequestBody user_nickname, @Part("gender")RequestBody gender, @Part MultipartBody.Part part_head);
public class UpdateUserHTTPResult {
    private long time;  //服務器響應時間
    private int code;  //響應碼 0表示正常
    private String msg;  //錯誤信息
    private Map<String, String> data;

    public long getTime() {
        return time;
    }
    public int getCode() {
        return code;
    }
    public String getMsg() {
        return msg;
    }
    public String getIsok(){
        return data.get("isok");
    }
    public String getAvatar_url(){
        return data.get("avatar_url");
    }
}
RequestBody requestUserID = RequestBody.create(MediaType.parse("multipart/form-data"), user_id);
            RequestBody requestUserNickname = RequestBody.create(MediaType.parse("multipart/form-data"), user_nickname);
            RequestBody requestGender = RequestBody.create(MediaType.parse("multipart/form-data"), gender);
            //將頭像圖片存儲爲圖片
            Bitmap bitmap = ((BitmapDrawable)iv_user_head.getDrawable()).getBitmap();
            ImageUtils.saveImage(bitmap, "temp.png");
            // 建立RequestBody,傳入參數:"multipart/form-data",File
            File imgFile = new File(Environment.getExternalStorageDirectory(),getString(R.string.app_name)+"/temp.png");
            RequestBody fileRequestBody = RequestBody.create(MediaType.parse("multipart/form-data"), imgFile);
            // 建立MultipartBody.Part,用於封裝文件數據
            MultipartBody.Part requestImgPart = MultipartBody.Part.createFormData("avatar", imgFile.getName(), fileRequestBody);
            httpAPI.update_user("Bearer "+myApp.getUser_token(),requestUserID, requestUserNickname, requestGender, requestImgPart)
                    .subscribeOn(Schedulers.newThread())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Observer<UpdateUserHTTPResult>() {
                        @Override
                        public void onCompleted() {
                            Log.d(TAG, "onCompleted: ");
                            dialog_busying.dismiss();
                        }

                        @Override
                        public void onError(Throwable e) {
                            Log.d(TAG, "onError: "+e.toString());
                            myApp.MakeToast("網絡出錯");
                            dialog_busying.dismiss();
                        }

                        @Override
                        public void onNext(UpdateUserHTTPResult updateUserHTTPResult) {
                            Log.d(TAG, "onNext: Time "+updateUserHTTPResult.getTime());
                            Log.d(TAG, "onNext: Code "+updateUserHTTPResult.getCode());
                            Log.d(TAG, "onNext: Msg "+updateUserHTTPResult.getMsg());
                            Log.d(TAG, "onNext: Isok "+updateUserHTTPResult.getIsok());
                            Log.d(TAG, "onNext: Avatar_url "+updateUserHTTPResult.getAvatar_url());
                            if(updateUserHTTPResult.getIsok().equals("true")){  //若是保存成功
                                //更新本地的用戶暱稱
                                String user_nickname = et_user_nickname.getText().toString();
                                myApp.setUser_nickname(user_nickname);
                                myApp.setUser_head_url(updateUserHTTPResult.getAvatar_url());
                                if (selector_gender == 0) myApp.setUser_gender("male");
                                else if (selector_gender == 1) myApp.setUser_gender("female");
                                editor.putString("user_nickname", myApp.getUser_nickname());
                                editor.putString("user_head_url", myApp.getUser_head_url());
                                editor.putString("user_gender",myApp.getUser_gender());
                                editor.commit();
                                myApp.MakeToast("保存成功");
                                Log.d(TAG, "onNext: 保存成功");
                                EventBus.getDefault().post("change_user_info");
                            }
                            else{
                                myApp.MakeToast("保存失敗");
                                Log.d(TAG, "onNext: 保存失敗");
                            }
                            dialog_busying.dismiss();
                        }
                    });

 

上面是表單上傳數據,若是是要JSON上傳數據,則:

interface APIStore {
   @Headers({"Content-Type: application/json","Accept: application/json"})//須要添加頭
   @POST ("vdyweb/ws/rest/Login")
   Call<ResponseBody>getMessage(@Body RequestBody info);   // 請求體味RequestBody 類型

PS:這裏的數據類型是@Body,與表單不一樣

public class Info {
    String account;
    String password;
 
    public Info(String account, String password) {
        this.account = account;
        this.password = password;
    }
}
Info info=new Info("test","123456");   /*** 利用Gson 將對象轉json字符串*/
Gson gson=new Gson();
String obj=gson.toJson(info);
retrofit=new Retrofit.Builder().baseUrl(BASE_LOGIN_URL).build();
RequestBody body=RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),obj);
相關文章
相關標籤/搜索