استفاده از Rest API با کتابخانه رتروفیت در اندروید

سلام به توسعه دهندگان مبتدی اندروید ، در این آموزش من کتابخانهRetrofit را به شما معرفی می کنم و همچنین سعی می کنم راهنمای گام به گام نحوه استفاده از JSOn object با استفاده از کتابخانه رتروفیت (retrofit) را ارائه دهم. این عمل مستلزم این است که شما با Java و توسعه برنامه Android آشنا باشید.رتروفیت (retrofit) چیست؟رتروفیت (retrofit) یک کتابخانه Rest Client (کتابخانه راهنما) است که در Android و Java برای ایجاد درخواست HTTP و همچنین پردازش پاسخ HTTP از REST API استفاده می شود. این توسط Square ایجاد شده است ، همچنین می توانید از ساختار مقاومتی برای دریافت ساختارهای داده غیر از JSON ، به عنوان مثال SimpleXML و Jackson استفاده کنید. قبل از ادامه ، بیایید به طور خلاصه REST Client و REST API را در متن خود تعریف کنیم. در بحث ما Rest Client، کتابخانه Retrofit است که در سمت client (Android) برای درخواست HTTP به REST API ، در بحث ما ، The Movie DB API و همچنین پردازش پاسخ ، مورد استفاده قرار می گیرد.Rest APIمجموعه ای از توابع را تعریف می کند که توسعه دهندگان می توانند درخواست ها را انجام دهند و از طریق پروتکل HTTP مانند GET و POST پاسخ دریافت کنند. موضوع ما ، The Movie DB (TMDB) API REST API است.طبق گفته Square ، سازندگان مستندات Retrofit ، رتروفیت HTTP API شما را به رابط جاوا تبدیل می کند. کد نمونه برای رابط و روش اعلام شده در آن به شرح زیر است:public interface GitHubService {@GET(&quotusers/{user}/repos&quot)Call<List<Repo>> listRepos(@Path(&quotuser&quot) String user);@GET(&quotgroup/{id}/users&quot)Call<List<User>> groupList(@Path(&quotid&quot) int groupId);}هر متدی در داخل یک رابط نشان دهنده یک تماس ممکن API است. برای تعیین نوع درخواست و نشانی اینترنتی نسبی ، باید دارای حاشیه نویسی HTTP (GET ، POST و غیره) باشد. مقدار بازگشتی پاسخ را در یک شی با نوع نتیجه مورد انتظار می قرار میدهد .@GET(“group/{id}/users”)Call<List<User>> groupList(@Path(“id”) int groupId, @Query(“sort”) String sort);همچنین شما میتوانید از بلاک های جایگرین و جایگزین های پرس و جو یا کوئری برای تنظیم urlاستفاده کنید. یک بلاک جایگیزین به urlنسبی با {}اضافه میشود.به کمک علامت @pathدر پارامتر های متد.2. یک کلاس Retrofit که پیاده سازی رابط GitHubService را ایجاد می کند. کد نمونه زیر در کلاس Retrofit قرار دارد و این نحوه ایجاد نمونه ای از Retrofit و پیاده سازی متد () listRepos در GitHubService Interface است.Retrofit retrofit = new Retrofit.Builder().baseUrl(“https://api.github.com/&quot).build();GitHubService service = retrofit.create(GitHubService.class);Call<List<Repo>> repos = service.listRepos(“Gino Osahon”);Retrofit Converters: مبدل های رتروفیت مانند توافق نامه بین سرویس گیرنده Android و سرور در مورد قالبی است که داده ها در آن نشان داده می شوند. هر دو طرف می توانند توافق کنند که برای ارتباطات ما ، قالب انتقال داده ها JSON خواهد بود ، مانند مورد ما در این آموزش. به یاد داشته باشید که گفتم جدا از مبدل ساختار JSON ، ما موارد دیگری را نیز داریم و در اینجا برخی از آنها توسط Retrofit پشتیبانی می شود.Gson:برای نقشه برداری JSON است و می تواند با dependency زیر اضافه شود:compile ‘com.squareup.retrofit2:converter-gson:2.2.0’SimpleXML:برای نقشه برداری XML است. برای build.gradle خود به خط زیر نیاز دارید:compile ‘com.squareup.retrofit2:convertersimplexml:2.2.0’jackson:جکسون جایگزینی برای Gson است و ادعا می کند که در نقشه برداری از داده های JSON سریعتر است. این تنظیمات سفارشی سازی بسیار بیشتری را به شما ارائه می دهد و ممکن است ارزش بررسی داشته باشد. می توانید آن را با موارد زیر اضافه کنید:compile ‘com.squareup.retrofit2:converter-jackson:2.2.0’3-همچنین ما برای ارتباط با Api باید مجوز اینترنت را در فایل manifest بنویسیم.<uses-permission android:name=”android.permission.INTERNET”/>4-پرونده App Build.gradle پروژه خود را باز کنید و dependency های زیر را به آن اضافه کنید:compile ‘com.squareup.picasso:picasso:2.5.2’compile ‘com.squareup.retrofit2:retrofit:2.1.0’compile ‘com.squareup.retrofit2:converter-gson:2.1.0’compile ‘com.android.support:recyclerview-v7:25.0.0’5- بیایید یک کلاس به نام Movie.java درون پکیج model ایجاد کنیم که یک POJO ساده برای نگهداری همه فیلدها و ارائه روش های گیرنده و تنظیم کننده برای فیلدهایی است که ما در شی object پاسخ JSON انتظار داریم. کد زیر را در پرونده Movie.java رد کنید.public class Movie {@SerializedName(&quotposter_path&quot)private String posterPath;@SerializedName(&quotadult&quot)private boolean adult;@SerializedName(&quotoverview&quot)private String overview;@SerializedName(&quotrelease_date&quot)private String releaseDate;@SerializedName(&quotgenre_ids&quot)private List<Integer> genreIds = new ArrayList<Integer>();@SerializedName(&quotid&quot)private Integer id;@SerializedName(&quotoriginal_title&quot)private String originalTitle;@SerializedName(&quotoriginal_language&quot)private String originalLanguage;@SerializedName(&quottitle&quot)private String title;@SerializedName(&quotbackdrop_path&quot)private String backdropPath;@SerializedName(&quotpopularity&quot)private Double popularity;@SerializedName(&quotvote_count&quot)private Integer voteCount;@SerializedName(&quotvideo&quot)private Boolean video;@SerializedName(&quotvote_average&quot)private Double voteAverage;public Movie(String posterPath, boolean adult, String overview, String releaseDate, List<Integer> genreIds, Integer id,String originalTitle, String originalLanguage, String title, String backdropPath, Double popularity,Integer voteCount, Boolean video, Double voteAverage) {this.posterPath = posterPath;this.adult = adult;this.overview = overview;this.releaseDate = releaseDate;this.genreIds = genreIds;this.id = id;this.originalTitle = originalTitle;this.originalLanguage = originalLanguage;this.title = title;this.backdropPath = backdropPath;this.popularity = popularity;this.voteCount = voteCount;this.video = video;this.voteAverage = voteAverage;}public String getPosterPath() {return posterPath;}public void setPosterPath(String posterPath) {this.posterPath = posterPath;}public boolean isAdult() {return adult;}public void setAdult(boolean adult) {this.adult = adult;}public String getOverview() {return overview;}public void setOverview(String overview) {this.overview = overview;}public String getReleaseDate() {return releaseDate;}public void setReleaseDate(String releaseDate) {this.releaseDate = releaseDate;}public List<Integer> getGenreIds() {return genreIds;}public void setGenreIds(List<Integer> genreIds) {this.genreIds = genreIds;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getOriginalTitle() {return originalTitle;}public void setOriginalTitle(String originalTitle) {this.originalTitle = originalTitle;}public String getOriginalLanguage() {return originalLanguage;}public void setOriginalLanguage(String originalLanguage) {this.originalLanguage = originalLanguage;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getBackdropPath() {return backdropPath;}public void setBackdropPath(String backdropPath) {this.backdropPath = backdropPath;}public Double getPopularity() {return popularity;}public void setPopularity(Double popularity) {this.popularity = popularity;}public Integer getVoteCount() {return voteCount;}public void setVoteCount(Integer voteCount) {this.voteCount = voteCount;}public Boolean getVideo() {return video;}public void setVideo(Boolean video) {this.video = video;}public Double getVoteAverage() {return voteAverage;}public void setVoteAverage(Double voteAverage) {this.voteAverage = voteAverage;}}6. ما همچنین باید کلاس MovieResponse.java را در داخل بسته مدل ایجاد کنیم ، زیرا برخی از زمینه های اضافی مانند شماره صفحه را داریم. این کلاس شامل تمام فیلم های واکشی شده و اطلاعات اضافی است. MovieResponse.java را در زیر بسته مدل و کد زیر را ایجاد کنید.public class MovieResponse {@SerializedName(&quotpage&quot)private int page;@SerializedName(&quotresults&quot)private List<Movie> results;@SerializedName(&quottotal_results&quot)private int totalResults;@SerializedName(&quottotal_pages&quot)private int totalPages;public int getPage() {return page;}public void setPage(int page) {this.page = page;}public List<Movie> getResults() {return results;}public void setResults(List<Movie> results) {this.results = results;}public int getTotalResults() {return totalResults;}public void setTotalResults(int totalResults) {this.totalResults = totalResults;}public int getTotalPages() {return totalPages;}public void setTotalPages(int totalPages) {this.totalPages = totalPages;}}7- بنابراین یک رابط با نام MovieApiService.java و گذشته کدهای زیر ایجاد کنید.public interface MovieApiService {@GET(“movie/top_rated”)Call<MovieResponse> getTopRatedMovies(@Query(“api_key”) String apiKey);}8. اکنون کلاس MainActivty.java را ایجاد می کنیم که Activity است که در آن از Movie DB API درخواست می کنیم. MainActivity.java را باز کرده و کدهای زیر را وارد کنید.public class MainActivity extends AppCompatActivity{private static final String TAG = MainActivity.class.getSimpleName();public static final String BASE_URL = &quothttp://api.themoviedb.org/3/"private static Retrofit retrofit = null;private RecyclerView recyclerView = null;// insert your themoviedb.org API KEY hereprivate final static String API_KEY = &quot"@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);recyclerView = (RecyclerView) findViewById(R.id.recycler_view);recyclerView.setHasFixedSize(true);recyclerView.setLayoutManager(new LinearLayoutManager(this));connectAndGetApiData();}// This method create an instance of Retrofit// set the base urlpublic void connectAndGetApiData(){if (retrofit == null) {retrofit = new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).build();}MovieApiService movieApiService = retrofit.create(MovieApiService.class);Call<MovieResponse> call = movieApiService.getTopRatedMovies(API_KEY);call.enqueue(new Callback<MovieResponse>() {@Overridepublic void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {List<Movie> movies = response.body().getResults();recyclerView.setAdapter(new MoviesAdapter(movies, R.layout.list_item_movie, getApplicationContext()));Log.d(TAG, &quotNumber of movies received: &quot + movies.size());}@Overridepublic void onFailure(Call<MovieResponse> call, Throwable throwable) {Log.e(TAG, throwable.toString());}});}رتروفیت (Retrofit) داده های API را روی یک thread پس زمینه بارگیری و تبدیل می کند و سپس نتایج را با متد های onResponse یا onFailure به thread UI باز می گرداند.9- زمان آن فرا رسیده است که نتیجه بدست آمده از query API با استفاده از کدهای فوق در طرح UI نمایش داده شود. ما باید یک طرح ایجاد کنیم که شامل 4 تا ویو متن یا متن نمایشی( TextView ) و 2 تصویر نمایشی (image view) باشد.فایل activity_main.xmlرا باز کنید و کد زیر را در آن کپی کنید.<?xml version=”1.0&quot encoding=”utf-8&quot?><LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android&quotxmlns:tools=”http://schemas.android.com/tools&quotandroid:layout_width=”match_parent”android:layout_height=”match_parent”tools:context=”app.movie.tutorial.com.activity.MainActivity”><android.support.v7.widget.RecyclerViewandroid:id=”@+id/recycler_view”android:scrollbars=”vertical”android:layout_width=”match_parent”android:layout_height=”match_parent”/></LinearLayout>یک layout با نام list_item_movie.Xml در پوشه layout ایجاد کنید.<?xml version=”1.0&quot encoding=”utf-8&quot?><LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android&quotandroid:id=”@+id/movies_layout”android:layout_width=”match_parent”android:layout_height=”wrap_content”android:gravity=”center_vertical”android:minHeight=”72dp”android:orientation=”horizontal”android:padding=”16dp”><LinearLayoutandroid:layout_width=”0dp”android:layout_height=”wrap_content”android:layout_weight=”1&quotandroid:orientation=”vertical”><ImageViewandroid:id=”@+id/movie_image”android:layout_width=”wrap_content”android:layout_height=”wrap_content”android:layout_gravity=”top”android:paddingRight=”16dp”/><TextViewandroid:id=”@+id/title”android:layout_width=”wrap_content”android:layout_height=”wrap_content”android:paddingRight=”16dp”android:textStyle=”bold”android:textColor=”@color/colorBlack”android:textSize=”16sp” /><TextViewandroid:id=”@+id/date”android:layout_width=”wrap_content”android:layout_height=”wrap_content”android:paddingRight=”16dp”android:textColor=”@color/colorGreyLight” /><TextViewandroid:id=”@+id/description”android:layout_width=”wrap_content”android:layout_height=”wrap_content”android:maxLines=”3&quotandroid:paddingRight=”16dp”android:textColor=”@color/colorGreyLight” /></LinearLayout><LinearLayoutandroid:layout_width=”wrap_content”android:layout_height=”35dp”android:orientation=”horizontal”><ImageViewandroid:id=”@+id/rating_image”android:layout_width=”15dp”android:layout_height=”15dp”android:layout_centerInParent=”true”android:scaleType=”centerCrop”android:src=”@drawable/star”android:tint=”@color/colorAccent” /><TextViewandroid:id=”@+id/rating”android:layout_width=”wrap_content”android:layout_height=”wrap_content”android:layout_marginLeft=”8dp”android:text=”5.0&quot /></LinearLayout></LinearLayout>آداپتور (Adapter) یک الگوی مشترک است که به اتصال داده کمک می کند ، بنابراین اجازه دهید آداپتور (انطباق دهنده ) را برای این کار پیاده سازی کنیم. یک کلاس به نام MoviesAdapter.java در زیر Adapter package ایجاد کنید.public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MovieViewHolder> {private List<Movie> movies;private int rowLayout;private Context context;public static final String IMAGE_URL_BASE_PATH=”http://image.tmdb.org/t/p/w342//&quotpublic MoviesAdapter(List<Movie> movies, int rowLayout, Context context) {this.movies = movies;this.rowLayout = rowLayout;this.context = context;}//A view holder inner class where we get reference to the views in the layout using their IDpublic static class MovieViewHolder extends RecyclerView.ViewHolder {LinearLayout moviesLayout;TextView movieTitle;TextView data;TextView movieDescription;TextView rating;ImageView movieImage;public MovieViewHolder(View v) {super(v);moviesLayout = (LinearLayout) v.findViewById(R.id.movies_layout);movieImage = (ImageView) v.findViewById(R.id.movie_image);movieTitle = (TextView) v.findViewById(R.id.title);data = (TextView) v.findViewById(R.id.date);movieDescription = (TextView) v.findViewById(R.id.description);rating = (TextView) v.findViewById(R.id.rating);}}@Overridepublic MoviesAdapter.MovieViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {View view = LayoutInflater.from(parent.getContext()).inflate(rowLayout, parent, false);return new MovieViewHolder(view);}@Overridepublic void onBindViewHolder(MovieViewHolder holder, final int position) {String image_url = IMAGE_URL_BASE_PATH + movies.get(position).getPosterPath();Picasso.with(context).load(image_url).placeholder(android.R.drawable.sym_def_app_icon).error(android.R.drawable.sym_def_app_icon).into(holder.movieImage);holder.movieTitle.setText(movies.get(position).getTitle());holder.data.setText(movies.get(position).getReleaseDate());holder.movieDescription.setText(movies.get(position).getOverview());holder.rating.setText(movies.get(position).getVoteAverage().toString());}@Overridepublic int getItemCount() {return movies.size();}}منبع:Consuming REST API using Retrofit Library in Android