Статьи

Начало работы с HTTP-клиентом Retrofit 2

Конечный продукт
Что вы будете создавать

Retrofit — это безопасный для типов HTTP-клиент для Android и Java. Модернизация позволяет легко подключаться к веб-службе REST путем перевода API в интерфейсы Java. В этом руководстве я покажу вам, как использовать одну из самых популярных и часто рекомендуемых библиотек HTTP, доступных для Android.

Эта мощная библиотека позволяет легко использовать данные JSON или XML, которые затем анализируются в простые старые объекты Java (POJO). Запросы GET , POST , PUT , PATCH и DELETE могут быть выполнены.

Как и большинство программного обеспечения с открытым исходным кодом, Retrofit был построен поверх некоторых других мощных библиотек и инструментов. За кулисами Retrofit использует OkHttp (от того же разработчика) для обработки сетевых запросов. Кроме того, Retrofit не имеет встроенного конвертера JSON для анализа объектов JSON в Java. Вместо этого он поддерживает следующие библиотеки JSON-конвертеров:

  • Gson: com.squareup.retrofit:converter-gson
  • Джексон: com.squareup.retrofit:converter-jackson
  • Моши: com.squareup.retrofit:converter-moshi

Для буферов протокола Retrofit поддерживает:

  • Protobuf: com.squareup.retrofit2:converter-protobuf
  • Провод: com.squareup.retrofit2:converter-wire

А для XML Retrofit поддерживает:

  • Простая структура: com.squareup.retrofit2:converter-simpleframework

Разработка собственной безопасной HTTP-библиотеки для взаимодействия с REST API может быть очень сложной задачей: вам приходится работать со многими функциями, такими как создание соединений, кэширование, повторение неудачных запросов, многопоточность, анализ ответов, обработка ошибок и многое другое. С другой стороны, дооснащение очень хорошо спланировано, задокументировано и протестировано — проверенная в сражениях библиотека, которая сэкономит вам много драгоценного времени и головной боли.

В этом руководстве я объясню, как использовать Retrofit 2 для обработки сетевых запросов, создав простое приложение для запроса последних ответов из Stack Exchange API. Мы GET запросы GET , указав конечную точку — /answers answers, добавленную к базовому URL-адресу https://api.stackexchange.com/2.2 /, — затем получим результаты и отобразим их в виде переработчика. Я также покажу вам, как это сделать с помощью RxJava для удобного управления потоком состояний и данных.

MainActivity Android Studio и создайте новый проект с пустым действием MainActivity .

Создать новую пустую активность

После создания нового проекта объявите следующие зависимости в вашем build.gradle . Зависимости включают в себя представление переработчика, библиотеку Retrofit, а также библиотеку Google Gson для преобразования JSON в POJO (простые старые объекты Java), а также интеграцию Retrofit Gson.

1
2
3
4
5
6
7
8
9
// Retrofit
compile ‘com.squareup.retrofit2:retrofit:2.1.0’
 
// JSON Parsing
compile ‘com.google.code.gson:gson:2.6.1’
compile ‘com.squareup.retrofit2:converter-gson:2.1.0’
 
// recyclerview
compile ‘com.android.support:recyclerview-v7:25.0.1’

Не забудьте синхронизировать проект для загрузки этих библиотек.

Для выполнения сетевых операций нам нужно включить INTERNET   разрешение в манифесте приложения: AndroidManifest.xml .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version=»1.0″ encoding=»utf-8″?>
<manifest xmlns:android=»http://schemas.android.com/apk/res/android»
          package=»com.chikeandroid.retrofittutorial»>
 
    <uses-permission android:name=»android.permission.INTERNET» />
 
    <application
            android:allowBackup=»true»
            android:icon=»@mipmap/ic_launcher»
            android:label=»@string/app_name»
            android:supportsRtl=»true»
            android:theme=»@style/AppTheme»>
        <activity android:name=».MainActivity»>
            <intent-filter>
                <action android:name=»android.intent.action.MAIN»/>
 
                <category android:name=»android.intent.category.LAUNCHER»/>
            </intent-filter>
        </activity>
    </application>
 
</manifest>

Мы собираемся создавать наши модели автоматически из наших данных ответов JSON, используя очень полезный инструмент: jsonschema2pojo .

Скопируйте и вставьте https://api.stackexchange.com/2.2/answers?order=desc&sort=activity&site=stackoverflow в адресную строку браузера (или вы можете использовать Postman, если вы знакомы с этим инструментом). Затем нажмите Enter — это выполнит запрос GET для данной конечной точки. В ответ вы увидите массив JSON-объектов. На снимке экрана ниже показан ответ JSON с использованием Postman.

Ответ API на запрос GET
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
{
  «items»: [
    {
      «owner»: {
        «reputation»: 1,
        «user_id»: 6540831,
        «user_type»: «registered»,
        «profile_image»: «https://www.gravatar.com/avatar/6a468ce8a8ff42c17923a6009ab77723?s=128&d=identicon&r=PG&f=1»,
        «display_name»: «bobolafrite»,
        «link»: «http://stackoverflow.com/users/6540831/bobolafrite»
      },
      «is_accepted»: false,
      «score»: 0,
      «last_activity_date»: 1480862271,
      «creation_date»: 1480862271,
      «answer_id»: 40959732,
      «question_id»: 35931342
    },
    {
      «owner»: {
        «reputation»: 629,
        «user_id»: 3054722,
        «user_type»: «registered»,
        «profile_image»: «https://www.gravatar.com/avatar/0cf65651ae9a3ba2858ef0d0a7dbf900?s=128&d=identicon&r=PG&f=1»,
        «display_name»: «jeremy-denis»,
        «link»: «http://stackoverflow.com/users/3054722/jeremy-denis»
      },
      «is_accepted»: false,
      «score»: 0,
      «last_activity_date»: 1480862260,
      «creation_date»: 1480862260,
      «answer_id»: 40959731,
      «question_id»: 40959661
    },
    …
  ],
  «has_more»: true,
  «backoff»: 10,
  «quota_max»: 300,
  «quota_remaining»: 241
}

Скопируйте этот ответ JSON либо из браузера, либо из Почтальона.

Теперь посетите jsonschema2pojo и вставьте ответ JSON в поле ввода.

Выберите тип источника JSON , стиль аннотации Gson и снимите флажок Разрешить дополнительные свойства .

интерфейс jsonschema2pojo

Затем нажмите кнопку « Просмотр» , чтобы сгенерировать объекты Java.

вывод jsonschema2pojo

Вам может быть интересно, что @SerializedName аннотации @SerializedName и @Expose в этом сгенерированном коде. Не волнуйся, я все объясню!

Аннотация @SerializedName необходима Gson для сопоставления ключей JSON с нашими полями. В соответствии с соглашением Java о присвоении имен camelCase для свойств членов класса, не рекомендуется использовать подчеркивания для разделения слов в переменной. @SerializedName помогает переводить между двумя.

1
2
3
@SerializedName(«quota_remaining»)
@Expose
private Integer quotaRemaining;

В приведенном выше примере мы говорим Gson, что наш ключ JSON quota_remaining должен быть сопоставлен с полем Java quotaRemaining . Если бы оба эти значения были одинаковыми, т. quotaRemaining Если бы наш JSON-ключ был quotaRemaining как и поле Java, тогда не было бы необходимости в аннотации @SerializedName для поля, потому что Gson отобразил бы их автоматически.

Аннотация @Expose указывает, что этот член должен быть @Expose для сериализации или десериализации JSON.

Теперь вернемся к Android Studio. Создайте новый подпакет внутри основного пакета и назовите его data . Внутри нового пакета данных создайте другой пакет и назовите его модель . Внутри модельного пакета создайте новый класс Java и назовите его Owner . Теперь скопируйте класс Owner , созданный jsonschema2pojo, и вставьте его в созданный вами класс Owner .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
 
public class Owner {
 
    @SerializedName(«reputation»)
    @Expose
    private Integer reputation;
    @SerializedName(«user_id»)
    @Expose
    private Integer userId;
    @SerializedName(«user_type»)
    @Expose
    private String userType;
    @SerializedName(«profile_image»)
    @Expose
    private String profileImage;
    @SerializedName(«display_name»)
    @Expose
    private String displayName;
    @SerializedName(«link»)
    @Expose
    private String link;
    @SerializedName(«accept_rate»)
    @Expose
    private Integer acceptRate;
 
 
    public Integer getReputation() {
        return reputation;
    }
 
    public void setReputation(Integer reputation) {
        this.reputation = reputation;
    }
 
    public Integer getUserId() {
        return userId;
    }
 
    public void setUserId(Integer userId) {
        this.userId = userId;
    }
 
    public String getUserType() {
        return userType;
    }
 
    public void setUserType(String userType) {
        this.userType = userType;
    }
 
    public String getProfileImage() {
        return profileImage;
    }
 
    public void setProfileImage(String profileImage) {
        this.profileImage = profileImage;
    }
 
    public String getDisplayName() {
        return displayName;
    }
 
    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }
 
    public String getLink() {
        return link;
    }
 
    public void setLink(String link) {
        this.link = link;
    }
 
    public Integer getAcceptRate() {
        return acceptRate;
    }
 
    public void setAcceptRate(Integer acceptRate) {
        this.acceptRate = acceptRate;
    }
}

Сделайте то же самое для нового класса Item , скопированного из jsonschema2pojo.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
 
public class Item {
 
    @SerializedName(«owner»)
    @Expose
    private Owner owner;
    @SerializedName(«is_accepted»)
    @Expose
    private Boolean isAccepted;
    @SerializedName(«score»)
    @Expose
    private Integer score;
    @SerializedName(«last_activity_date»)
    @Expose
    private Integer lastActivityDate;
    @SerializedName(«creation_date»)
    @Expose
    private Integer creationDate;
    @SerializedName(«answer_id»)
    @Expose
    private Integer answerId;
    @SerializedName(«question_id»)
    @Expose
    private Integer questionId;
    @SerializedName(«last_edit_date»)
    @Expose
    private Integer lastEditDate;
 
    public Owner getOwner() {
        return owner;
    }
 
    public void setOwner(Owner owner) {
        this.owner = owner;
    }
 
    public Boolean getIsAccepted() {
        return isAccepted;
    }
 
    public void setIsAccepted(Boolean isAccepted) {
        this.isAccepted = isAccepted;
    }
 
    public Integer getScore() {
        return score;
    }
 
    public void setScore(Integer score) {
        this.score = score;
    }
 
    public Integer getLastActivityDate() {
        return lastActivityDate;
    }
 
    public void setLastActivityDate(Integer lastActivityDate) {
        this.lastActivityDate = lastActivityDate;
    }
 
    public Integer getCreationDate() {
        return creationDate;
    }
 
    public void setCreationDate(Integer creationDate) {
        this.creationDate = creationDate;
    }
     
    public Integer getAnswerId() {
        return answerId;
    }
 
    public void setAnswerId(Integer answerId) {
        this.answerId = answerId;
    }
 
    public Integer getQuestionId() {
        return questionId;
    }
 
    public void setQuestionId(Integer questionId) {
        this.questionId = questionId;
    }
 
    public Integer getLastEditDate() {
        return lastEditDate;
    }
 
    public void setLastEditDate(Integer lastEditDate) {
        this.lastEditDate = lastEditDate;
    }
}

Наконец, создайте класс с именем   SOAnswersResponse для возвращенных ответов StackOverflow. Вы найдете код для этого класса в jsonschema2pojo в качестве Example . Убедитесь, что вы обновили имя класса до SOAnswersResponse где бы оно ни происходило.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
 
import java.util.List;
 
public class SOAnswersResponse {
 
    @SerializedName(«items»)
    @Expose
    private List<Item> items = null;
    @SerializedName(«has_more»)
    @Expose
    private Boolean hasMore;
    @SerializedName(«backoff»)
    @Expose
    private Integer backoff;
    @SerializedName(«quota_max»)
    @Expose
    private Integer quotaMax;
    @SerializedName(«quota_remaining»)
    @Expose
    private Integer quotaRemaining;
 
    public List<Item> getItems() {
        return items;
    }
 
    public void setItems(List<Item> items) {
        this.items = items;
    }
 
    public Boolean getHasMore() {
        return hasMore;
    }
 
    public void setHasMore(Boolean hasMore) {
        this.hasMore = hasMore;
    }
 
    public Integer getBackoff() {
        return backoff;
    }
 
    public void setBackoff(Integer backoff) {
        this.backoff = backoff;
    }
 
    public Integer getQuotaMax() {
        return quotaMax;
    }
 
    public void setQuotaMax(Integer quotaMax) {
        this.quotaMax = quotaMax;
    }
 
    public Integer getQuotaRemaining() {
        return quotaRemaining;
    }
 
    public void setQuotaRemaining(Integer quotaRemaining) {
        this.quotaRemaining = quotaRemaining;
    }
}

Чтобы отправлять сетевые запросы к REST API с Retrofit, нам нужно создать экземпляр с помощью класса Retrofit.Builder и настроить его с помощью базового URL.

Создайте новый пакет подпакета внутри пакета data и назовите его remote . Теперь внутри remote создайте класс Java и назовите его RetrofitClient . Этот класс создаст синглтон Retrofit. Для модификации необходим базовый URL-адрес для создания своего экземпляра, поэтому мы будем передавать URL-адрес при вызове RetrofitClient.getClient(String baseUrl) . Затем этот URL будет использоваться для построения экземпляра в строке 13. Мы также указываем нужный нам JSON-конвертер (Gson) в строке 14.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
 
public class RetrofitClient {
 
    private static Retrofit retrofit = null;
 
    public static Retrofit getClient(String baseUrl) {
        if (retrofit==null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }
}

Внутри удаленного пакета создайте интерфейс и назовите его SOService . Этот интерфейс содержит методы, которые мы собираемся использовать для выполнения HTTP-запросов, таких как GET , POST , PUT , PATCH и DELETE . Для этого урока мы собираемся выполнить запрос GET .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
import com.chikeandroid.retrofittutorial.data.model.SOAnswersResponse;
 
import java.util.List;
 
import retrofit2.Call;
import retrofit2.http.GET;
 
public interface SOService {
 
   @GET(«/answers?order=desc&sort=activity&site=stackoverflow»)
   Call<SOAnswersResponse> getAnswers();
     
   @GET(«/answers?order=desc&sort=activity&site=stackoverflow»)
   Call<SOAnswersResponse> getAnswers(@Query(«tagged») String tags);
}

Аннотация @GET явно определяет тот GET который будет выполнен после @GET метода. Каждый метод в этом интерфейсе должен иметь аннотацию HTTP, которая предоставляет метод запроса и относительный URL. Доступно пять встроенных аннотаций: @GET , @POST , @PUT , @DELETE и @HEAD .

Во втором определении метода мы добавили параметр запроса для фильтрации данных с сервера. Retrofit имеет @Query("key") можно использовать вместо жесткого кодирования в конечной точке. Значение ключа представляет имя параметра в URL. Он будет добавлен в URL при помощи Retrofit. Например, если мы передадим значение "android" в качестве аргумента getAnswers(String tags) , полный URL будет:

1
https://api.stackexchange.com/2.2/answers?order=desc&sort=activity&site=stackoverflow&tagged=android

Параметры методов интерфейса могут иметь следующие аннотации:

@Path подстановка переменных для конечной точки API
@Query указывает имя ключа запроса со значением аннотированного параметра
@Body полезная нагрузка для вызова POST
@Header указывает заголовок со значением аннотированного параметра

Теперь собираемся создать служебный класс. Мы ApiUtils это ApiUtils . Этот класс будет иметь базовый URL-адрес в качестве статической переменной, а также предоставлять интерфейс SOService нашему приложению через статический метод getSOService() .

1
2
3
4
5
6
7
8
public class ApiUtils {
 
    public static final String BASE_URL = «https://api.stackexchange.com/2.2/»;
 
    public static SOService getSOService() {
        return RetrofitClient.getClient(BASE_URL).create(SOService.class);
    }
}

Так как результаты будут отображаться в виде переработчика , нам нужен адаптер. В следующем фрагменте кода показан класс AnswersAdapter .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
public class AnswersAdapter extends RecyclerView.Adapter<AnswersAdapter.ViewHolder> {
 
    private List<Item> mItems;
    private Context mContext;
    private PostItemListener mItemListener;
 
    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
 
        public TextView titleTv;
        PostItemListener mItemListener;
 
        public ViewHolder(View itemView, PostItemListener postItemListener) {
            super(itemView);
            titleTv = (TextView) itemView.findViewById(android.R.id.text1);
 
            this.mItemListener = postItemListener;
            itemView.setOnClickListener(this);
        }
 
        @Override
        public void onClick(View view) {
            Item item = getItem(getAdapterPosition());
            this.mItemListener.onPostClick(item.getAnswerId());
 
            notifyDataSetChanged();
        }
    }
 
    public AnswersAdapter(Context context, List<Item> posts, PostItemListener itemListener) {
        mItems = posts;
        mContext = context;
        mItemListener = itemListener;
    }
 
    @Override
    public AnswersAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
 
        Context context = parent.getContext();
        LayoutInflater inflater = LayoutInflater.from(context);
 
        View postView = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
 
        ViewHolder viewHolder = new ViewHolder(postView, this.mItemListener);
        return viewHolder;
    }
 
    @Override
    public void onBindViewHolder(AnswersAdapter.ViewHolder holder, int position) {
 
        Item item = mItems.get(position);
        TextView textView = holder.titleTv;
        textView.setText(item.getOwner().getDisplayName());
    }
 
    @Override
    public int getItemCount() {
        return mItems.size();
    }
 
    public void updateAnswers(List<Item> items) {
        mItems = items;
        notifyDataSetChanged();
    }
 
    private Item getItem(int adapterPosition) {
        return mItems.get(adapterPosition);
    }
 
    public interface PostItemListener {
        void onPostClick(long id);
    }
}

Внутри onCreate() объекта MainActivity мы инициализируем экземпляр интерфейса SOService (строка 9), представление рециркулятора, а также адаптер. Наконец, мы вызываем метод loadAnswers() .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private AnswersAdapter mAdapter;
   private RecyclerView mRecyclerView;
   private SOService mService;
 
   @Override
   protected void onCreate (Bundle savedInstanceState) {
       super.onCreate( savedInstanceState );
       setContentView(R.layout.activity_main );
       mService = ApiUtils.getSOService();
       mRecyclerView = (RecyclerView) findViewById(R.id.rv_answers);
       mAdapter = new AnswersAdapter(this, new ArrayList<Item>(0), new AnswersAdapter.PostItemListener() {
 
           @Override
           public void onPostClick(long id) {
               Toast.makeText(MainActivity.this, «Post id is» + id, Toast.LENGTH_SHORT).show();
           }
       });
 
       RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
       mRecyclerView.setLayoutManager(layoutManager);
       mRecyclerView.setAdapter(mAdapter);
       mRecyclerView.setHasFixedSize(true);
       RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST);
       mRecyclerView.addItemDecoration(itemDecoration);
 
       loadAnswers();
   }

Метод loadAnswers() создает сетевой запрос, вызывая enqueue() . Когда ответ возвращается, Retrofit помогает нам проанализировать ответ JSON для списка объектов Java. (Это стало возможным благодаря использованию GsonConverter .)

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
public void loadAnswers() {
    mService.getAnswers().enqueue(new Callback<SOAnswersResponse>() {
    @Override
    public void onResponse(Call<SOAnswersResponse> call, Response<SOAnswersResponse> response) {
 
        if(response.isSuccessful()) {
            mAdapter.updateAnswers(response.body().getItems());
            Log.d(«MainActivity», «posts loaded from API»);
        }else {
            int statusCode = response.code();
            // handle request errors depending on status code
        }
    }
 
    @Override
    public void onFailure(Call<SOAnswersResponse> call, Throwable t) {
       showErrorMessage();
        Log.d(«MainActivity», «error loading from API»);
 
    }
});
}

enqueue() асинхронно отправляет запрос и уведомляет ваше приложение обратным вызовом, когда возвращается ответ. Поскольку этот запрос является асинхронным, Retrofit обрабатывает его в фоновом потоке, чтобы основной поток пользовательского интерфейса не блокировался и не мешал.

Чтобы использовать enqueue() , вы должны реализовать два метода обратного вызова:

  • onResponse()
  • onFailure()

Только один из этих методов будет вызван в ответ на данный запрос.

  • onResponse() : вызывается для полученного ответа HTTP. Этот метод вызывается для ответа, который можно правильно обработать, даже если сервер возвращает сообщение об ошибке. Поэтому, если вы получите код состояния 404 или 500, этот метод все равно будет вызываться. Чтобы получить код состояния для обработки ситуаций на их основе, вы можете использовать метод response.code() . Вы также можете использовать метод isSuccessful() чтобы выяснить, находится ли код состояния в диапазоне 200-300, что указывает на успех.
  • onFailure() : вызывается, когда при подключении к серверу возникло сетевое исключение или произошло непредвиденное исключение при обработке запроса или обработке ответа.

Для выполнения синхронного запроса вы можете использовать метод execute() . Имейте в виду, что синхронные методы в основном потоке / интерфейсе пользователя блокируют любые действия пользователя Поэтому не выполняйте синхронные методы в основном потоке Android / пользовательском интерфейсе! Вместо этого запустите их в фоновом потоке.

Теперь вы можете запустить приложение.

Пример результатов из StackOverflow

Если вы являетесь поклонником RxJava, вы можете легко реализовать Retrofit с помощью RxJava. В Retrofit 1 он был интегрирован по умолчанию, но в Retrofit 2 вам необходимо включить некоторые дополнительные зависимости. Модификация поставляется с адаптером по умолчанию для выполнения экземпляров Call . Таким образом, вы можете изменить механизм выполнения Retrofit, включив в него RxJava, включив RxJava CallAdapter .

Добавьте зависимости.

1
2
3
compile ‘io.reactivex:rxjava:1.1.6’
compile ‘io.reactivex:rxandroid:1.2.1’
compile ‘com.squareup.retrofit2:adapter-rxjava:2.1.0’

Добавьте новый CallAdapter RxJavaCallAdapterFactory.create() при создании экземпляра Retrofit.

01
02
03
04
05
06
07
08
09
10
public static Retrofit getClient(String baseUrl) {
    if (retrofit==null) {
        retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }
    return retrofit;
}

Теперь обновите методы getAnswers() чтобы они возвращали Observable s:

1
2
3
4
5
@GET(«/answers?order=desc&sort=activity&site=stackoverflow»)
Observable<SOAnswersResponse> getAnswers();
      
@GET(«/answers?order=desc&sort=activity&site=stackoverflow»)
Observable<SOAnswersResponse> getAnswers(@Query(«tagged») String tags);

При выполнении запросов наш анонимный подписчик отвечает на поток наблюдаемой, который генерирует события, в нашем случае SOAnswersResponse . Затем метод onNext вызывается, когда наш подписчик получает любое событие, которое onNext а затем передается нашему адаптеру.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
@Override
public void loadAnswers() {
    mService.getAnswers().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<SOAnswersResponse>() {
                @Override
                public void onCompleted() {
                }
 
                @Override
                public void onError(Throwable e) {
                }
 
                @Override
                public void onNext(SOAnswersResponse soAnswersResponse) {
                    mAdapter.updateAnswers(soAnswersResponse.getItems());
                }
            });
}

Чтобы узнать больше о RxJava и RxAndroid, ознакомьтесь с разделом Начало работы с ReactiveX на Android от Ашрафа Хатибелагала.

  • Android
    Начало работы с ReactiveX на Android
    Ашраф Хатхибелагал

В этом уроке вы узнали о Retrofit: почему вы должны его использовать и как. Я также объяснил, как добавить интеграцию RxJava с Retrofit. В моем следующем посте я покажу вам, как выполнять POST , PUT и DELETE , как отправлять данные в Form-Urlencoded и как отменять запросы.

Чтобы узнать больше о модернизации, обратитесь к официальной документации . А пока ознакомьтесь с другими нашими курсами и учебными пособиями по разработке приложений для Android.

  • Связь в приложении для Android с EventBus

  • Практический параллелизм на Android с HaMeR

  • Android с нуля: использование API REST

  • Начните с шаблона приложения для Android за 60 секунд