iT邦幫忙

2023 iThome 鐵人賽

DAY 14
0
Mobile Development

Android Studio開發過程和介紹系列 第 14

【DAY 14】 怎麼使用Retrofit抓取API資料

  • 分享至 

  • xImage
  •  

前言

Retrofit是一個強大、方便的工具,可以讓開發人員更容易地執行網絡請求並處理 API 數據,並且它還可以結合其他的套件一起使用,使其的功能可以變得更加強大,也因為它簡單好上手,所以也很適合拿來給初新者使用
這次會使用網路上提供的假資料,網址是https://jsonplaceholder.typicode.com/albums

由於Retrofit是屬於第三方套件,所以需要添加dependencies,也因為其性質是要向網路請求抓取API資料,所以也要開啟網路請求的功能。

使用Retrofit的步驟

  1. 加入需要的dependencies
  2. 開啟網路請求功能
  3. 建立Retrofit環境
  4. 建立接收資料的class
  5. 建立抓取Api的interface
  6. 調用Retrofit抓取所需的Api資料

dependencies

使用Retrofit需要先加入必要的dependencies

    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'

加入完後,上面會跳出這串https://ithelp.ithome.com.tw/upload/images/20230914/201615009lmXorXgOQ.png
點選Sync Now再讓他跑一下就可以了。

網路請求

網路請求要在AndroidManifest.xml進行,在application上方加上

<uses-permission android:name="android.permission.INTERNET" />

https://ithelp.ithome.com.tw/upload/images/20230914/201615000Y6mz0jeDG.png
就像上面展示的一樣,到此就完成了Retrofit的前置作業。

Retrofit環境建立

雖然Retrofit的環境建立寫在MainActivity裡面也是可以,但是這邊推薦將環境建立寫在外面,這麼做最大的好處就是可以讓所有需要使用到Api的Activity都可以調用,就不需要每次都寫一次重複的架構,下面就開始講解:
首先要先建立一個Class,這邊我取名為ApiClient,接著就開始寫Retrofit的環境

import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class ApiClient {
    public Retrofit testWebData(){
      return new Retrofit.Builder()//建立Retrofit
              .baseUrl("https://jsonplaceholder.typicode.com/")
              //輸入Api資料網站
              .addConverterFactory(GsonConverterFactory.create())
              //添加Gson轉換器,這個幫助我們將http上的資料轉成Retrofit能夠處理的Json數據並將其轉換為Java對象
              .build();
              //將環境建立起來
    }
}

可以看到,這裡建立了一個方法,用來回傳建立好的Retrofit環境,後面要使用到這個Api的Activity就可以呼叫ApiClient裡面的testWebData再create就好。

接收資料的class

建立一個class叫DataResponse用來接收資料

public class DataResponse {
    private int userId;
    private int id;
    private String title;

    @Override
    public String toString() {
        return "DataResponse{" +
                "\nuserId=" + userId +
                ",\n id=" + id +
                ",\n title='" + title + '\'' +
                '}';
    }

    public int getUserId() {
        return userId;
    }

    public int getId() {
        return id;
    }

    public String getTitle() {
        return title;
    }
}

這邊要宣告Api資料裡面,需要取得的資料的資料型態,例如:id是int型態,那就要宣告為int。
這裡要注意!不只型態要對,資料的名字也一定要對,否則你資料不管如何都一定抓不到,資料宣告有兩種方式,正式一點的就是寫成private,想要方便一點的就是用public,兩者的差別在於,前者要用getter和setter,後者則可以直接調用。
可以看到這個部分

    private int userId;
    private int id;
    private String title;

我是宣告為private,且所有的資料都是符合Api資料的型態跟名字
下面則可以看到我重新撰寫了一個自己的toString(),關於這個我推薦使用內建的方式撰寫,會比自己寫得更加快速,後續再根據自己的需求改變部分的樣式就好,使用方法入下:

依序從左到右,先點擊右鍵後選擇Generate > toString() > 最後將要打包在toString的資料選好在按OK,這樣就會自動生成自己的toString囉~
建立toString是為了要將取得的資料一次顯示,但是如果今天我只是需要其中的一個資料要怎麼做呢?
接著往下看到這裡

public int getUserId() {
        return userId;
    }

    public int getId() {
        return id;
    }

    public String getTitle() {
        return title;
    }

這個部分就是getter,也就是給外面要取資料用的,有了這個方法外面就可以指定要哪一個資料,建立方法我一樣推薦使用內建的Generate來生成,步驟如下:

依序從左到右,先點擊右鍵後選擇Generate > Getter > 最後選完要使用Getter再按下OK,就建立好Getter囉~

interface

建立ineterface的方法跟class再同個地方

只要點選下面的interface就可以建立了,這邊我命名為GetApi

public interface GetApi {
    @GET("albums/{id}")
    //在/後面加上id可以查到那個id的資料
    Call<DataResponse> getJsonData(@Path("id") int id);
    //用Path將傳入的id填入{}裡面
}

一個interface裡面可以放入多個請求api的方法,新增的方式就像上面這樣
使用@Get請求資料,()後放的是網址以及參數
再來使用Call去呼叫,<>裡面放入你創建的接收資料的class
然後命名,後面@Path是為了將參數填到上面{}裡面,這邊也要記得資料的形態要正確。

布局設定

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="0.5"
        android:gravity="center"
        android:textSize="30sp"
        android:textStyle="bold"
        android:background="@drawable/border"
        android:text="TextView" />

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="0.2"
        android:ems="10"
        android:inputType="text"
        android:textSize="35sp"
        android:gravity="center"
        android:background="@drawable/border"
        android:hint="輸入數字(1~100)"/>

    <Button
        android:id="@+id/button"
        android:layout_width="300dp"
        android:layout_height="0dp"
        android:layout_weight="0.3"
        android:textSize="40sp"
        android:background="@drawable/border"
        android:text="查詢" />
</LinearLayout>

由於這個Api資料可以透過搜尋id的方式來抓取不同的資料,所以這次的設計就加上了EditText跟Button,做到搜尋的功能。

MainActivity

private TextView textView;
    private Button button;
    private EditText editText;
    private ApiClient apiClient;
    private GetApi getApi;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.textView);
        button = findViewById(R.id.button);
        editText = findViewById(R.id.editText);
        apiClient = new ApiClient();
        getApi = apiClient.testWebData().create(GetApi.class);

        button.setOnClickListener(view -> {
            Call call = getApi.getJsonData(Integer.parseInt(editText.getText().toString()));
            call.enqueue(new Callback() {
                @Override
                public void onResponse(Call call, Response response) {
                    textView.setText(response.body().toString());
                }

                @Override
                public void onFailure(Call call, Throwable t) {
                    textView.setText("資料抓取失敗");
                }
            });
        });
    }

首先要宣告ApiClient、GetApi

    private ApiClient apiClient;
    private GetApi getApi;

接著進行初始化跟綁定

        apiClient = new ApiClient();
        getApi = apiClient.testWebData().create(GetApi.class);

以上就已經成功創立一個Retrofit的環境
接著就是開始抓取Api的資料,這邊我寫在Button的點擊事件內,概念是點擊搜尋後,就將EditText內輸入的資料丟給Retrofit,讓它依照這個參數去尋找我想要的資料

        button.setOnClickListener(view -> {
            Call call = getApi.getJsonData(Integer.parseInt(editText.getText().toString()));
            call.enqueue(new Callback() {
                @Override
                public void onResponse(Call call, Response response) {
                    textView.setText(response.body().toString());
                }

                @Override
                public void onFailure(Call call, Throwable t) {
                    textView.setText("資料抓取失敗");
                }
            });
        });

首先看到這個部分

Call call = getApi.getJsonData(Integer.parseInt(editText.getText().toString()));

這裡創建了一個Call,同時呼叫了getApi裡面的getJsonData並且向裡面傳入了EditText輸入的內容
再來這個部分

call.enqueue(new Callback() {
                @Override
                public void onResponse(Call call, Response response) {
                    textView.setText(response.body().toString());
                }

                @Override
                public void onFailure(Call call, Throwable t) {
                    textView.setText("資料抓取失敗");
                }
            });

這裡使用的是Retrofit的異步執行請求,使用enqueue可以將要取Api資料的動作切換到背景執行,並在請求完後調用Callback的方法
接著就會得到下面兩個方法onResponseonFailure,分別代表得到資料後做的事,還有資料抓取失敗時要做的事
因此我在抓到資料的地方設定TextView填入抓取到的資料,讀取資料的方法要用到response.body(),後面接到在DataResponse裡面寫到的方法
,失敗的部分就將TextView填入資料抓取失敗的字串。

執行結果

下一篇我會介紹可以跟Retrofit結合的套件RxJava,RxJava在使用上比較方便,切換theard的方法也更加清楚,是個很常會用來跟Retrofit結合的套件。


上一篇
【DAY 13】 簡單介紹TabLayout
下一篇
【DAY 15】 Retrofit結合RxJava
系列文
Android Studio開發過程和介紹30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言