Android Retrofitのチュートリアルとサンプル。

Retrofitとは?Retrofitは、Square社によって最初に作られたTypesafe HTTP Clientです。

Retrofitの役割は、HTTP APIをJavaのインターフェイスにすることです。

public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

です。

この授業では、アンドロイド開発に関して、RetrofitとRetrofitの例について見ていきます。この授業では、RetrofitとRetrofitのサンプルを使って、HTTP経由でウェブサービスと簡単に対話する方法を見ていきます。

Retrofitの要件は何ですか?

Retrofitの要件は非常に手厚くなっています。

    1. Java 7 以上。
    1. Android 2.3以上

Retrofitのインストール方法は?

Retrofitはサードパーティ製のHTTPクライアントライブラリで、androidとjavaに対応しています。そのため、プロジェクトにインストールする必要があります。

もし、アンドロイドフレームワークに標準的に含まれているネットワーククラスをお探しでしたら、HttpURLConnectionをご覧ください。

それ以外の場合、Retrofitは3つの方法でインストールすることができます。

**1. jarとしてインストールする。

基本的には、Retrofitのjarをダウンロードし、android studioにjarライブラリとして追加します。

例えば、私はretrofit 2.4.0を使用しました。こちらからダウンロードできます。

それ以外の場合は、最新版をこちらで確認することができます。

2. mavenを経由して

Maven、別名、Apache Mavenは、主にJavaプロジェクトで使用されるビルド自動化ツールです。

このため、主に2つの役割があります。

  1. プロジェクトがどのようにビルドされるかを記述する。
    1. プロジェクトの依存関係を記述する。

では、Retrofitをjavaプロジェクトにおける依存関係として記述してみましょう。

<dependency>
  <groupId>com.squareup.retrofit2</groupId>
  <artifactId>retrofit</artifactId>
  <version>2.4.0</version>
</dependency>

3. Gradle 経由で

Gradleはandroid studioで使用されているビルドシステムです_。

アンドロイドプロジェクトを作成している場合、この方法でretrofitをインストールする可能性があります。これは、アンドロイドの公式開発IDEであるAndroid Studioを使用する可能性が高いためです。そして、android studioはgradleのビルドシステムを利用しています。

その場合、アプリレベルのbuild.gradleに移動して、依存関係のDSLに以下の記述を追加する必要があります。

implementation 'com.squareup.retrofit2:retrofit:2.4.0'

共通の後付けインターフェース、クラス、およびメソッドです。

1. コール

Webサーバにリクエストを送り、レスポンスを返すRetrofitのメソッドの呼び出しを表すRetrofitのインターフェイスです。その名の通り、基本的にはあなたが行うHTTP Callを表します。

各呼び出しは、それぞれ独自の HTTP リクエストとレスポンスのペアを生成します。同じパラメータで複数の呼び出しを行うこともできます。ただし、そのためにはcloneを使用します。これは、ポーリングの実装や、失敗した呼び出しの再試行に使用することができます。

HTTPコールを行う場合、同期または非同期で行うことができます。同期的に呼び出すには、execute()メソッドを使用します。一方、非同期で呼び出す場合は enqueue() メソッドを使用します。

呼び出しをキャンセルしたい場合は、cancel() メソッドを使用します。

以下はその定義です。

public interface Call<T> extends Cloneable

この場合、Tは成功したレスポンスボディのタイプを表していることに注意してください。

Enqueue()

これは Call<T> インターフェースに属するメソッドである。このインターフェースは、あなたが行う HTTP Call を表していると話しました。

そして、通常、同期または非同期の呼び出しやリクエストを行うことができます。もし、非同期で呼び出したい場合は、このメソッドを使用します。

以下はその定義です。

public abstract void enqueue(retrofit2.Callback<T> callback)

このメソッドは、サーバーとの通信、リクエストの作成、またはレスポンスの処理にエラーが発生した場合に備えて、リクエストを非同期で送信し、そのレスポンスをコールバックに通知します。

以下は、簡単な使用例です。

        Call<List<Spacecraft>> call = myAPIService.getSpacecrafts();
        call.enqueue(new Callback<List<Spacecraft>>() {

            @Override
            public void onResponse(Call<List<Spacecraft>> call, Response<List<Spacecraft>> response) {
                myProgressBar.setVisibility(View.GONE);
                populateRecyclerView(response.body());
            }
            @Override
            public void onFailure(Call<List<Spacecraft>> call, Throwable throwable) {
                myProgressBar.setVisibility(View.GONE);
                Toast.makeText(MainActivity.this, throwable.getMessage(), Toast.LENGTH_LONG).show();
            }
        });

3. コールバック

サーバーからの応答やオフラインのリクエストの通信を担当するメソッドを定義したインターフェースです。

以下はその定義である。

public interface Callback<T>

上の T は成功したレスポンスボディの種類を表します。

通常、与えられたリクエストに応答して1つのメソッドが呼び出されます。このメソッドはRetrofitのコールバックエグゼキュータを使って実行されます。何も指定しない場合、以下のデフォルトが使用されます。

  1. Android。1. Android: コールバックはアプリケーションのメイン(UI)スレッドで実行されます。
    1. JVM。コールバックは、リクエストを実行したバックグラウンドスレッドで実行されます。

以下は使用例です。

new Callback<List<Spacecraft>>() {

            @Override
            public void onResponse(Call<List<Spacecraft>> call, Response<List<Spacecraft>> response) {
                myProgressBar.setVisibility(View.GONE);
                populateRecyclerView(response.body());
            }
            @Override
            public void onFailure(Call<List<Spacecraft>> call, Throwable throwable) {
                myProgressBar.setVisibility(View.GONE);
                Toast.makeText(MainActivity.this, throwable.getMessage(), Toast.LENGTH_LONG).show();
            }
        }

4. レトロフィット

これは、宣言されたメソッドにアノテーションを付けてリクエストの方法を定義することで、JavaインターフェイスをHTTP呼び出しに適応させる役割を持つクラスです。

以下はその定義です。

public final class Retrofit extends Object

これを使用するには、このインスタンスを作成する必要があります。しかし、これはビルダーを使って行うもので、実装を生成するためにインターフェイスをcreateに渡します。例えば

   Retrofit retrofit = new Retrofit.Builder()
       .baseUrl("https://api.example.com/")
       .addConverterFactory(GsonConverterFactory.create())
       .build();

   MyApi api = retrofit.create(MyApi.class);
   Response<User> user = api.getUser().execute();

あるいは、そのインスタンスを返してくれる簡単なファクトリークラスを作ることもできます。

    static class RetrofitClientInstance {

        private static Retrofit retrofit;
        private static final String BASE_URL = "https://raw.githubusercontent.com/";

        public static Retrofit getRetrofitInstance() {
            if (retrofit == null) {
                retrofit = new Retrofit.Builder()
                        .baseUrl(BASE_URL)
                        .addConverterFactory(GsonConverterFactory.create())
                        .build();
            }
            return retrofit;
        }
    }

そして、そのクラスをこのように使う。

        MyAPIService myAPIService = RetrofitClientInstance.getRetrofitInstance().create(MyAPIService.class);

Kotlin Android Retrofit Movies の例

この例では、IMDBのウェブサイトから映画のリストを取得し、recyclerviewでレンダリングする方法について説明します。アイテムはRetrofitで取得されます。画像はPicassoでレンダリングしています。

以下はデモの画像です。

ステップ1:プロジェクトの作成

まず、空の Android Studio プロジェクトを作成します。

ステップ2: 依存関係

まず、Retrofitを依存関係として追加します。Retrofitのconverter-gsonと並べて追加します。

    implementation "com.squareup.retrofit2:retrofit:$retrofitVersion"
    implementation "com.squareup.retrofit2:converter-gson:$retrofitConverterGsonVer"

また、RecyclerViewとCardViewの依存関係を追加します。

    implementation "androidx.recyclerview:recyclerview:$supportVer"
    implementation "androidx.cardview:cardview:$supportVer"

また、イメージローダーであるPicassoの依存関係を追加します。

    implementation "com.squareup.picasso:picasso:$picassoVersion"

ステップ3: レイアウト設計

次に、レイアウトを設計します。2つのレイアウトを用意します。

(a). list_row.xml

これは、recyclerviewの1つの行に展開されます。画像とテキストを含むカードビューを用意する予定です。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <androidx.cardview.widget.CardView
        android:id="@+id/card_view"
        android:layout_width="match_parent"
        android:layout_height="240dp"
        android:layout_gravity="center"
        android:layout_margin="5dp"
        android:background="#fff"
        card_view:cardCornerRadius="2dp"
        card_view:contentPadding="10dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <ProgressBar
                android:id="@+id/progress_bar"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:visibility="gone" />

            <ImageView
                android:id="@+id/image_view_movie"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:scaleType="fitXY" />

            <TextView
                android:id="@+id/movie_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginStart="10dp"
                android:textColor="@android:color/black"
                android:textSize="18sp"
                android:textStyle="bold" />

        </LinearLayout>

    </androidx.cardview.widget.CardView>

</LinearLayout>

(b). activity_main.xml.

MainActivity` レイアウトに、アイテムのリストをレンダリングするための recyclerview を追加します。

<?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"
    tools:context="com.developers.usingretrofit.MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/movie_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:layout_marginEnd="5dp"
        android:layout_marginStart="5dp" />
</LinearLayout>

ステップ4:定数の作成

定数とは、値が変化しない変数のことです。例えば、プロジェクトのベースURLや画像URLには、このような変数が必要になります。定数.kt`というファイルを作成し、以下のコードを追加します。

Constants.kt

class Constants {

    companion object {
        @JvmField
        val BASE_URL = "https://api.themoviedb.org/3/movie/";
        @JvmField
        val IMAGE_BASE_URL = "http://image.tmdb.org/t/p/w185/"
    }

}

ステップ5:モデルクラスの作成

モデルクラスは2つ用意します。

(a). MovieResult.kt

これは、映画の結果呼び出しを表現するクラスです。このモデルクラスは、結果のリストと同様に、ページ、結果合計、ページ合計のようなプロパティを持つことになります。

import com.google.gson.annotations.Expose
import com.google.gson.annotations.SerializedName

data class MovieResult(@SerializedName("page")
                  @Expose
                  var page: Int? = null,
                  @SerializedName("total_results")
                  @Expose
                  var totalResults: Int? = null,
                  @SerializedName("total_pages")
                  @Expose
                  var totalPages: Int? = null,
                  @SerializedName("results")
                  @Expose
                  var results: List<Result>? = null)

(b). 結果.kt

この結果クラスは、単一の映画と、タイトル、人気度、ジャンル ID などのそのプロパティを表します。


import com.google.gson.annotations.Expose
import com.google.gson.annotations.SerializedName

data class Result(
        @SerializedName("vote_count")
        @Expose
        var voteCount: Int? = null,
        @SerializedName("id")
        @Expose
        var id: Int? = null,
        @SerializedName("video")
        @Expose
        var video: Boolean? = null,
        @SerializedName("vote_average")
        @Expose
        var voteAverage: Double? = null,
        @SerializedName("title")
        @Expose
        var title: String? = null,
        @SerializedName("popularity")
        @Expose
        var popularity: Double? = null,
        @SerializedName("poster_path")
        @Expose
        var posterPath: String? = null,
        @SerializedName("original_language")
        @Expose
        var originalLanguage: String? = null,
        @SerializedName("original_title")
        @Expose
        var originalTitle: String? = null,
        @SerializedName("genre_ids")
        @Expose
        var genreIds: List<Int>? = null,
        @SerializedName("backdrop_path")
        @Expose
        var backdropPath: String? = null,
        @SerializedName("adult")
        @Expose
        var adult: Boolean? = null,
        @SerializedName("overview")
        @Expose
        var overview: String? = null,
        @SerializedName("release_date")
        @Expose
        var releaseDate: String? = null)

ステップ6:APIサービスの作成

これは、HTTPリクエストを表すメソッドを含む、単なるインターフェースです。

ApiInterface.kt


import com.developers.usingretrofit.model.MovieResult
import com.developers.usingretrofit.utils.Constants
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Query

interface ApiInterface {

    @GET("popular")
    fun getMovies(@Query("api_key") key: String,
                  @Query("page") page: Int): Call<MovieResult>

    companion object Factory {

        fun create(): ApiInterface {

            val retrofit = Retrofit.Builder()
                    .addConverterFactory(GsonConverterFactory.create())
                    .baseUrl(Constants.BASE_URL)
                    .build()

            return retrofit.create(ApiInterface::class.java);

        }

    }

}

ステップ 7: アダプタの作成

ムービーリストをrecyclerviewに表示するためには、アダプターが必要です。以下のように RecyclerView.Adapter を拡張して作成します。

MovieAdapter.kt

import android.content.Context
import android.net.Uri
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.developers.usingretrofit.R
import com.developers.usingretrofit.model.Result
import com.developers.usingretrofit.utils.Constants
import com.squareup.picasso.Callback
import com.squareup.picasso.Picasso
import kotlinx.android.synthetic.main.list_row.view.*

class MovieAdapter(val context: Context, private val resultList: List<Result>?) : RecyclerView.Adapter<MovieAdapter.MyViewHolder>() {

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        holder.bindItems(resultList?.get(position))
    }

    override fun getItemCount(): Int {
        return resultList?.size!!
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val view = LayoutInflater.from(context).inflate(R.layout.list_row, parent, false)
        return MyViewHolder(view)
    }

    class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        fun bindItems(result: Result?) {
            itemView.movie_title.text = result?.title
            val posterUri = Uri.parse(Constants.IMAGE_BASE_URL).buildUpon()
                    .appendEncodedPath(result?.posterPath)
                    .build()
            itemView.progress_bar.visibility = View.VISIBLE
            Picasso.with(itemView.context).load(posterUri.toString())
                    .into(itemView.image_view_movie, object : Callback {

                        override fun onError() {
                            //Show Error here
                        }

                        override fun onSuccess() {
                            itemView.progress_bar.visibility = View.GONE
                        }

                    })
        }
    }
}

ステップ8:MainActivityのコードを書く

以下は、MainActivityの全コードです。

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Toast
import androidx.recyclerview.widget.GridLayoutManager
import com.developers.usingretrofit.adapter.MovieAdapter
import com.developers.usingretrofit.model.MovieResult
import kotlinx.android.synthetic.main.activity_main.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val apiCall = ApiInterface.create()
        apiCall.getMovies(BuildConfig.TV_KEY, 1).enqueue(object : Callback<MovieResult> {
            override fun onFailure(call: Call<MovieResult>?, t: Throwable?) {
                showError(t?.message)
            }

            override fun onResponse(call: Call<MovieResult>?, response: Response<MovieResult>?) {
                val movieResponse = response?.body()
                val resultList = movieResponse?.results
                val layoutManager = GridLayoutManager(applicationContext,2)
                val adapter = MovieAdapter(applicationContext, resultList)
                movie_recycler_view.layoutManager = layoutManager
                movie_recycler_view.adapter = adapter
            }

        })
    }

    private fun showError(message: String?) {
        toast(message.toString())
    }

    fun Context.toast(msg: String) {
        Toast.makeText(applicationContext, msg, Toast.LENGTH_SHORT).show()
    }
}

実行

コードをコピーするか、以下のリンクからダウンロードし、ビルドして実行してください。

参考

参考リンクはこちらです。

番号とリンク
1. 例:ダウンロード 1. 例:ダウンロード
2. フォロー コード作成者 | Developers.IO
3. コード Apache 2.0 ライセンス

Categorized in: