1. 程式人生 > >Android使用Retrofit進行網路請求

Android使用Retrofit進行網路請求

Retrofit 簡介

用於Android和Java平臺的一款型別安全的HTTP客戶端,通過一個Java介面實現HTTP請求物件,如下:

public interface Github {
    @GET("/repos/{owner}/{repo}/contributors")
    Call<List<Contributor>> contributors(
            @Path("owner") String owner,
            @Path("repo") String repo);
}

Android 平臺使用示例

步驟如下:

  • 新增 Retrofit 相關依賴庫
//retrofit2 依賴庫
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
//Gson 資料解析器依賴庫
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
//okhttp3 輸出網路請求日誌依賴庫
implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1'
  • 建立接收伺服器返回資料對應的實體類
//建立接收伺服器返回資料的類
public class
Contributor {
public final String login; public final int contributions; public Contributor(String login, int contributions) { this.login = login; this.contributions = contributions; } }
  • 建立用於描述網路請求的介面
//建立用於網路請求的介面
public interface Github {
    @GET("/repos/{owner}/{repo}/contributors"
) Call<List<Contributor>> contributors( @Path("owner") String owner, @Path("repo") String repo); }
  • *配置列印網路請求日誌
HttpLoggingInterceptor loggingInterceptor;
//列印網路請求相關日誌
loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
      @Override
      public void log(String message) {
           //列印retrofit日誌
           Log.i("retrofitLog: ", message);
      }
});
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

//為了列印日誌,需要配置OkHttpClient
OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(loggingInterceptor)
                .build();
  • 建立Retrofit物件
Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(API_GITHUB_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
  • 建立網路請求介面例項
//建立網路介面例項
Github github = retrofit.create(Github.class);

//對傳送請求進行封裝
Call<List<Contributor>> call = github.contributors("square", "retrofit");
  • 傳送網路請求(非同步 / 同步)並對返回資料進行處理
//傳送同步請求時不能直接在UI執行緒進行,不然會報錯:NetworkOnMainThreadException
//傳送請求,獲取請求的資料
List<Contributor> contributors = call.execute().body();
StringBuilder result = new StringBuilder();
for (Contributor contributor : contributors) {
      result.append(contributor.login + " (" + contributor.contributions + ")\n");
}
Log.e("result", result.toString());

主要程式碼如下

  • MainActivity.java

    public class MainActivity extends AppCompatActivity {
    
    private TextView tv_request_result;
    public static final String API_GITHUB_URL = "https://api.github.com";
    HttpLoggingInterceptor loggingInterceptor;
    
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Bundle data = msg.getData();
            String result = data.getString("result");
            tv_request_result.setText(result);
        }
    };
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    
        //列印網路請求相關日誌
        loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
                //列印retrofit日誌
                Log.i("retrofitLog: ", message);
            }
        });
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    
        new Thread(runnable).start(); //不能在UI執行緒中進行網路請求
    
    }
    
    private void initView() {
        tv_request_result = (TextView) findViewById(R.id.tv_request_result);
    }
    
    //傳送網路請求
    private String request() throws IOException {
        //為了列印日誌,需要配置okhttp
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(loggingInterceptor)
                .build();
    
        //建立Retrofit物件
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(API_GITHUB_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    
        //建立網路介面例項
        Github github = retrofit.create(Github.class);
    
        //對傳送請求進行封裝
        Call<List<Contributor>> call = github.contributors("square", "retrofit");
    
        //傳送請求,獲取請求的資料
        List<Contributor> contributors = call.execute().body();
        StringBuilder result = new StringBuilder();
        for (Contributor contributor : contributors) {
            result.append(contributor.login + " (" + contributor.contributions + ")\n");
        }
        Log.e("result", result.toString());
        return result.toString();
    }
    
    //網路請求執行緒
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            try {
                String result = request();
                Message msg = new Message();
                Bundle data = new Bundle();
                data.putString("result", result);
                msg.setData(data);
                handler.sendMessage(msg);
            } catch (IOException e) {
                Log.e("request_erro", e.toString());
            }
        }
    };
    }
  • activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <TextView
                android:id="@+id/tv_request_result"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="20sp" />
        </ScrollView>
    </LinearLayout>
  • 程式執行結果
    這裡寫圖片描述
  • 網路請求日誌如下:
07-02 16:07:41.145 17443-17462/com.example.xuyue.learnretrofit I/retrofitLog:: --> GET https://api.github.com/repos/square/retrofit/contributors http/1.1
    --> END GET
07-02 16:07:43.275 17443-17462/com.example.xuyue.learnretrofit I/retrofitLog:: <-- 200 OK https://api.github.com/repos/square/retrofit/contributors (2129ms)
    Server: GitHub.com
    Date: Mon, 02 Jul 2018 08:07:45 GMT
    Content-Type: application/json; charset=utf-8
    Transfer-Encoding: chunked
    Status: 200 OK
    X-RateLimit-Limit: 60
    X-RateLimit-Remaining: 30
    X-RateLimit-Reset: 1530522209
    Cache-Control: public, max-age=60, s-maxage=60
07-02 16:07:43.276 17443-17462/com.example.xuyue.learnretrofit I/retrofitLog:: Vary: Accept
    ETag: W/"0313af265d6c3206fe7e38545918e2bf"
    Last-Modified: Mon, 02 Jul 2018 07:42:01 GMT
    X-GitHub-Media-Type: github.v3; format=json
    Link: <https://api.github.com/repositories/892275/contributors?page=2>; rel="next", <https://api.github.com/repositories/892275/contributors?page=5>; rel="last"
    Access-Control-Expose-Headers: ETag, Link, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
    Access-Control-Allow-Origin: *
    Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
    X-Frame-Options: deny
    X-Content-Type-Options: nosniff
    X-XSS-Protection: 1; mode=block
    Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
    Content-Security-Policy: default-src 'none'
    X-Runtime-rack: 0.075905
    X-GitHub-Request-Id: 90E0:3CD2:61BDD85:BCDE66D:5B39DD50
07-02 16:07:43.288 17443-17462/com.example.xuyue.learnretrofit I/retrofitLog:: [{"login":"JakeWharton","id":66577,"node_id":"MDQ6VXNlcjY2NTc3","avatar_url":"https://avatars0.githubusercontent.com/u/66577?v=4","gravatar_id":"","url":"https://api.github.com/users/JakeWharton","html_url":"https://github.com/JakeWharton","followers_url":"https://api.github.com/users/JakeWharton/followers","following_url":"https://api.github.com/users/JakeWharton/following{/other_user}","gists_url":"https://api.github.com/users/JakeWharton/gists{/gist_id}","starred_url":"https://api.github.com/users/JakeWharton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JakeWharton/subscriptions","organizations_url":"https://api.github.com/users/JakeWharton/orgs","repos_url":"https://api.github.com/users/JakeWharton/repos","events_url":"https://api.github.com/users/JakeWharton/events{/privacy}","received_events_url":"https://api.github.com/users/JakeWharton/received_events","type":"User","site_admin":false,"contributions":911},{"login":"swankjesse","id":133019,"node_id":"MDQ6VXNlcjEzMzAxOQ==","avatar_url":"https://avatars3.githubusercontent.com/u/133019?v=4","gravatar_id":"","url":"https://api.github.com/users/swankjesse","html_url":"https://github.com/swankjesse","followers_url":"https://api.github.com/users/swankjesse/followers","following_url":"https://api.github.com/users/swankjesse/following{/other_user}","gists_url":"https://api.github.com/users/swankjesse/gists{/gist_id}","starred_url":"https://api.github.com/users/swankjesse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/swankjesse/subscriptions","organizations_url":"https://api.github.com/users/swankjesse/orgs","repos_url":"https://api.github.com/users/swankjesse/repos","events_url":"https://api.github.com/users/swankjesse/events{/privacy}","received_events_url":"https://api.github.com/users/swankjesse/received_events","type":"User","site_admin":false,"contributions":224},{"login":"pforhan","id":331925,"node_id":"MDQ6VXNlcjMzMTkyNQ==","avatar_url":"https://avatars3.githubusercontent.com/u/331925?v=4","gravatar_id":"","url":"https://api.github.com/users/pforhan","html_url":"https://github.com/pforhan","followers_url":"https://api.github.com/users/pforhan/followers","following_url":"https://api.github.com/users/pforhan/following{/other_user}","gists_url":"https://api.github.com/users/pforhan/gists{/gist_id}","starred_url":"https://api.github.com/users/pforhan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pforhan/subscriptions","organizations_url":"https://api.github.com/users/pforhan/orgs","repos_url":"https://api.github.com/users/pforhan/repos","events_url":"https://api.github.com/users/pforhan/events{/privacy}","received_events_url":"https://api.github.com/users/pforhan/received_events","type":"User","site_admin":false,"contributions":48},{"login":"eburke","id":63761,"node_id":"MDQ6VXNlcjYzNzYx","avatar_url":"https://avatars0.githubusercontent.com/u/63761?v=4","gravatar_id":"","url":"https://api.github.com/users/eburke","html_url":"https://github.com/eburke","followers_url":"https://api.github.com/users/eburke/followers","following_url":"https://api.github.com/users/eburke/following{/other_user}","gists_url":"https://api.github.com/users/eburke/gists{/gist_id}","starred_url":"https://api.github.com/users/eburke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eburke/subscriptions","organizations_url":"https://api.github.com/users/eburke/orgs","repos_url":"https://api.github.com/users/eburke/repos","events_url":"https://api.github.com/users/eburke/events{/privacy}","received_events_url":"https://api.github.com/users/eburke/received_events","type":"User","site_admin":false,"contributions":36},{"login":"dnkoutso","id":310370,"node_id":"MDQ6VXNlcjMxMDM3MA==","avatar_url":"https://avatars2.githubusercontent.com/u/310370?v=4","gravatar_id":"","url":"https://api.github.com/users/dnkoutso","html_url":"https://github.com/dnkoutso","followers_url":"https://api.github.com/users/dnkoutso/followers","following_url":"https://api.github.com/users/d
    <-- END HTTP (28135-byte body)
  • 伺服器返回資料示例
{
    "login": "JakeWharton",
    "id": 66577,
    "node_id": "MDQ6VXNlcjY2NTc3",
    "avatar_url": "https://avatars0.githubusercontent.com/u/66577?v=4",
    "gravatar_id": "",
    "url": "https://api.github.com/users/JakeWharton",
    "html_url": "https://github.com/JakeWharton",
    "followers_url": "https://api.github.com/users/JakeWharton/followers",
    "following_url": "https://api.github.com/users/JakeWharton/following{/other_user}",
    "gists_url": "https://api.github.com/users/JakeWharton/gists{/gist_id}",
    "starred_url": "https://api.github.com/users/JakeWharton/starred{/owner}{/repo}",
    "subscriptions_url": "https://api.github.com/users/JakeWharton/subscriptions",
    "organizations_url": "https://api.github.com/users/JakeWharton/orgs",
    "repos_url": "https://api.github.com/users/JakeWharton/repos",
    "events_url": "https://api.github.com/users/JakeWharton/events{/privacy}",
    "received_events_url": "https://api.github.com/users/JakeWharton/received_events",
    "type": "User",
    "site_admin": false,
    "contributions": 911
  }