レトロフィット2の学習





Android開発の世界には興味深いライブラリがたくさんありますが、今日はSquare - Retrofitという会社の発案を検討します。 これはどんな獣ですか? (公式サイトによると)Retrofitは、AndroidおよびJava用のタイプセーフなHTTPクライアントです。 これは、クライアント/サーバーアプリケーションでAPIを操作するために不可欠なツールです。 約5年前、ネットワークを操作するAndroid開発者は、コールバック、AsyncTaskes、およびその他の「低レベル」なもので山のようなコードを変更する必要がありました。 そして、Squareはこのような素晴らしいライブラリ、Retrofitをリリースしました。



インターネットでは、ライブラリの2番目のバージョンでわかりやすいチュートリアルを見つけることができなかったため、今日はbash.imから投稿を受け取るアプリケーションの例を使用して処理します。



100回聞くよりも1回見る方が良い



UmoriliサイトAPIからデータを受信するアプリケーションを作成します。これは、bashからのデータのみを便利な解析形式で提供するためです。 これは、最終バージョンの外観です。







 もちろん、デザインは光りません 
さて、子供たち、準備はいいですか?



依存関係



Retrofitライブラリは、Gradle、Maven、Jarの3つの方法で接続できます。 それぞれの方法を説明します。



グラドル



ほとんどの場合、このツールはAndroid用のアプリケーションのビルドに使用されるため、不明な場合はこのオプションを使用してください:)(以降、Gradleは依存関係に使用されます)。



アプリケーションモジュールをbuild.gradleファイルに接続するには、 dependencies



セクションで次の行を挿入します。



 compile 'com.squareup.retrofit2:retrofit:2.1.0'
      
      





メイヴン



誰かがこの依存関係とアセンブリのシステムを使用する場合、依存関係のフラグメントは次のようになります。



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





ジャー



このオプションの使用は歓迎しませんが、気に入っている人もいます。 公式サイトからjarファイル( リンク )をダウンロードし、libsフォルダーにドロップします。



ライブラリ自体に加えて、JSONパーサーとRecyclerView-v7が必要なので、それらを接続します。



 compile 'com.squareup.retrofit2:converter-gson:2.1.0' // JSON, ,  ,  Jackson compile 'com.android.support:recyclerview-v7:25.0.0' //RecyclerView
      
      





依存関係が整理されたら、最も甘い部分である開発に移りましょう。 したがって、まず最初に、APIリクエストを記述する必要があります。



APIリクエストの説明



Retrofitを使用すると、POST、GET、PUT、DELETEを実行できる本格的なRESTクライアントを作成できます。 注釈は、要求のタイプおよびその他の側面を示すために使用されます。 たとえば、GETリクエストが必要であることを示すために、 GETメソッドの前、POSTリクエストのPOSTなどについて記述する必要があります。 リクエストのタイプの括弧内はターゲットアドレスです。 たとえば、GitHub APIを使用します。 特定のユーザーのリポジトリのリストを取得するための完全なURLは、 https://api.github.com/users/octocat/repos



: https://api.github.com/users/octocat/repos



として表すことができhttps://api.github.com/users/octocat/repos



。ここで、





リクエストパラメータはまだあります。たとえば、Umoriliへのリクエストでは、次のアドレスを使用します-https://umorili.herokuapp.com/api/get? name=bash&num=50



、ここでname=bash&num=50



はパラメータです。



ただし、説明は単なる注釈で終わるわけではありませんが、どこかで説明する必要があります。 そして、それらをインターフェースで説明します。 このアプリケーションの場合、インターフェースは次のようになります。



 package ru.mustakimov.retrofittutorial.api; import java.util.List; import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.Query; import ru.mustakimov.retrofittutorial.PostModel; public interface UmoriliApi { @GET("/api/get") Call<List<PostModel>> getData(@Query("name") String resourceName, @Query("num") int count); }
      
      





このインターフェースを分析しましょう。 Call<List<PostModel>>



型のオブジェクトを返すgetDataメソッドがあります。 メソッドは、常にタイプCall<T>



オブジェクトを返し、要求タイプ(GET、POST、PUT、DELETE)の注釈を持っている必要があります。



アノテーション@Query("name") String resourceName



は、クエリパラメーターとしてカップル名= <文字列値resourceName>を配置する必要がある@Query("name") String resourceName



示しています。



宛先アドレスにエイリアスがある場合、エイリアスを値に置き換えるには、関数パラメーターに@Path("< >") SomeType variable



を記述する必要があります。SomeTypeは任意の型(String、int、フロート)。



PostModelは、サーバー応答に基づいてjsonschema2pojo Webサイトによって生成されたクラスです。



ここにクラス自体があります
 package ru.mustakimov.retrofittutorial; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; public class PostModel { @SerializedName("site") @Expose private String site; @SerializedName("name") @Expose private String name; @SerializedName("desc") @Expose private String desc; @SerializedName("link") @Expose private String link; @SerializedName("elementPureHtml") @Expose private String elementPureHtml; /** * @return The site */ public String getSite() { return site; } /** * @param site The site */ public void setSite(String site) { this.site = site; } /** * @return Site name */ public String getName() { return name; } /** * @param name Site name */ public void setName(String name) { this.name = name; } /** * @return Site description */ public String getDesc() { return desc; } /** * @param desc Site description */ public void setDesc(String desc) { this.desc = desc; } /** * @return The link */ public String getLink() { return link; } /** * @param link The link */ public void setLink(String link) { this.link = link; } /** * @return The elementPureHtml */ public String getElementPureHtml() { return elementPureHtml; } /** * @param elementPureHtml The elementPureHtml */ public void setElementPureHtml(String elementPureHtml) { this.elementPureHtml = elementPureHtml; } }
      
      







リクエストの準備



リクエストを送信して結果を受信する前に、Retrofitとインターフェイスオブジェクトを初期化する必要があります。 アプリケーションに同じ機能を実行する何百ものオブジェクトがないように、Applicationから継承したクラスですべての初期化を行います。 コードは次のようになります。



 package ru.mustakimov.retrofittutorial; import android.app.Application; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; import ru.mustakimov.retrofittutorial.api.UmoriliApi; public class App extends Application { private static UmoriliApi umoriliApi; private Retrofit retrofit; @Override public void onCreate() { super.onCreate(); retrofit = new Retrofit.Builder() .baseUrl("https://umorili.herokuapp.com") //   .addConverterFactory(GsonConverterFactory.create()) //,    JSON'   .build(); umoriliApi = retrofit.create(UmoriliApi.class); // ,       } public static UmoriliApi getApi() { return umoriliApi; } }
      
      



PSは、Applicationクラスを使用することをマニフェストに登録することを忘れないでください



これで、どのクラスからでもAPIにアクセスできます。



データ検索



同期リクエストと非同期リクエストの2つの方法でリクエストを実行できます(したがって、データを受信します)。 同期(ブロッキング)受信では、Callタイプのオブジェクトのexecute()



メソッドを使用します。 この例では、コードは次のようになります。



 Response response = App.getApi().getData("bash", 50).execute();
      
      





実行の結果として、タイプResponse(response)のオブジェクトを取得します。ここから、 body()



メソッドを使用して解析済みのレスポンスを取得できます。



非同期受信の場合、 execute()



enqueue()



に置き換えます。ここで、パラメーターでコールバック関数(コールバック)を渡します。 この例では、次のようになります。



 App.getApi().getData("bash", 50).enqueue(new Callback<List<PostModel>>() { @Override public void onResponse(Call<List<PostModel>> call, Response<List<PostModel>> response) { //  ,    response.body()  null } @Override public void onFailure(Call<List<PostModel>> call, Throwable t) { //  } });
      
      





データマッピングの作成



すでにデータを受け取っていますが、今どのように表示するのですか? 私たちはRecyclerViewのアクティビティのマークアップを投入し、何らかの形でそれを呼び出します。 その後、要素のマークアップを作成します。



それは私が得たものです
activity_main.xml

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="ru.mustakimov.retrofittutorial.MainActivity"> <android.support.v7.widget.RecyclerView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:id="@+id/posts_recycle_view" android:layout_alignParentStart="true" /> </RelativeLayout>
      
      





post_item.xml

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:padding="5dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/postitem_post" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="    ,     ,     " android:textColor="?android:attr/textColorPrimary" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <TextView android:id="@+id/postitem_site" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Bash.im" android:layout_below="@+id/postitem_post" android:layout_alignParentRight="true" android:layout_alignParentEnd="true" android:gravity="end" android:textAlignment="textEnd" /> </RelativeLayout>
      
      







RecyclerViewのアダプタを作成した後:



アダプターコード
 package ru.mustakimov.retrofittutorial; import android.os.Build; import android.support.v7.widget.RecyclerView; import android.text.Html; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import java.util.List; public class PostsAdapter extends RecyclerView.Adapter<PostsAdapter.ViewHolder> { private List<PostModel> posts; public PostsAdapter(List<PostModel> posts) { this.posts = posts; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.post_item, parent, false); return new ViewHolder(v); } @Override public void onBindViewHolder(ViewHolder holder, int position) { PostModel post = posts.get(position); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { holder.post.setText(Html.fromHtml(post.getElementPureHtml(), Html.FROM_HTML_MODE_LEGACY)); } else { holder.post.setText(Html.fromHtml(post.getElementPureHtml())); } holder.site.setText(post.getSite()); } @Override public int getItemCount() { if (posts == null) return 0; return posts.size(); } class ViewHolder extends RecyclerView.ViewHolder { TextView post; TextView site; public ViewHolder(View itemView) { super(itemView); post = (TextView) itemView.findViewById(R.id.postitem_post); site = (TextView) itemView.findViewById(R.id.postitem_site); } } }
      
      







また、MainActivity.javaでは、RecyclerView、アダプターの初期化、およびデータの受信を規定しています。



そしてここにMainActivityがあります
 package ru.mustakimov.retrofittutorial; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.widget.Toast; import java.io.IOException; import java.util.ArrayList; import java.util.List; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; public class MainActivity extends AppCompatActivity { RecyclerView recyclerView; List<PostModel> posts; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); posts = new ArrayList<>(); recyclerView = (RecyclerView) findViewById(R.id.posts_recycle_view); LinearLayoutManager layoutManager = new LinearLayoutManager(this); recyclerView.setLayoutManager(layoutManager); PostsAdapter adapter = new PostsAdapter(posts); recyclerView.setAdapter(adapter); try { Response response = App.getApi().getData("bash", 50).execute(); } catch (IOException e) { e.printStackTrace(); } App.getApi().getData("bash", 50).enqueue(new Callback<List<PostModel>>() { @Override public void onResponse(Call<List<PostModel>> call, Response<List<PostModel>> response) { posts.addAll(response.body()); recyclerView.getAdapter().notifyDataSetChanged(); } @Override public void onFailure(Call<List<PostModel>> call, Throwable t) { Toast.makeText(MainActivity.this, "An error occurred during networking", Toast.LENGTH_SHORT).show(); } }); } }
      
      







GitHubではこのアプリケーションの完全なコードを見つけることができます。



All Articles