آموزش کامل کار با Retrofit 2.x بعنوان یک کلاینت REST

آموزش کامل کار با Retrofit 2.x بعنوان یک کلاینت REST

بروزرسانی : 5 ماه پیش

آموزش کار با کتابخانه ی retrofit در اندروید - آموزش رتروفیت اندروید - آموزش ارتباطات سروری اندروید

در این مقاله ی آموزشی قصد داریم بصورت جامع و کامل درباره ی کتابخانه Retrofit برای کلاینت Retrofit  آموزش دهیم 

 

Retrofit  چیست ؟ 

امروزه ارتباط بین اپ موبایل و سرور مسئله ی مهمی است و از اهمیت بالایی برخوردار است . از آنجایی که کار با HttpUrlConnection  سخت است کتابخانه های جانبی برای این کار ساخته شده اند از جمله کتابخانه ی volley و کتابخانه ی Retrofit که کار ارتباطات سروری را راحت میکنند  .

Retrofit یک کلاینت از نوع REST  برای زبان جاوا و اندروید است . این کتابخانه به شما کمک میکند تا به سادگی عمل دریافت و ارسال اطلاعات به وب سرویس هایی که مبتنی بر REST (یا هر نوع ساختار دیگر) هستند را انجام دهید . ارسالا و دریافت اطلاعات با فرمت JSON میباشد . بجای JSON شما میتوانید Retrofit را برای کار دیگر نوع داده ها مثل XML یا نوع های دیگر تنظیم کنید . 

Retrofit از کتابخانه ی OkHttp  برای پروتکل HTTP استفاده میکند یعنی یه جورایی میشه گفت retrofit بر پایه ی OkHttp پیاده سازی شده است . 

 

نحوه ی استفاده از Retrofit 

برای کار با Retfofit شما اساسا نیاز به کلاس های زیر خواهید داشت 

  • یک کلاس مدل که اطلاعات مدل JSON را استفاده میکند
  • Interface هایی که عملیات HTTP  را تعریف میکند
  • کلاس Retrofit.Builder - برای تعریف خیلی از چیزها مثل URL  مربوط به درخواست HTTP و ... استفاده میشود

هر متود از اینترفیس یک درخواست از API را فراهم میکند . منظور از این درخواست ها همان درخواست های HTTP است که میتواند از نوع GET , POST یا هر چیز دیگری باشد . 

نتایج درون آبجکت Call  بسته بندی میشوند . مثال زیر را ببینید : 

 

@GET("users")
Call<List<User>> getUsers();

شما میتوانید URL درخواست را تعریف کنید و برای تعریف کردن این مورد @path را در کد زیر ببینید : 

@GET("users/{name}/commits")
Call<List<Commit>> getCommitsByName(@Path("name") String name);

پارامترهای کوئری روی @Query تنظیم میشوند . کد زیر را ببینید : 

@GET("users")
Call<User> getUserById(@Query("id") Integer id);

خب @Body هم مشخصه که بدنه اصلی ارسال ماست : 

@POST("users")
Call<User> postUser(@Body User user)

 

نصب و راه اندازی Retrofit  در محیط android studio

خب برای استفاده از Retrofit باید ابتدا انرا نصب کنید . همچنین ما نیاز به Gson هم داریم که باید آنرا هم نصب کنیم و همچنین converter مربوطه به Gson را !

ابتدا وارد فایل Build.gradle در محیط android studio از نوع Module شده و در بخش dependencies سه خط زیر را کپی کرده و دکمه sync را بزنید.

compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.google.code.gson:gson:2.6.1'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'

البته برای بارگزاری و نصب شدن این کتابخانه چون کشور ایران تحریم است کاری انجام دهید که IP شما عوض شود مثلا از vpn استفاده کنید . 

چون این کتابخانه ها از اینترنت برای برقراری ارتباطات سروری استفاده میکنند شما باید مجوز اینترنت را به اپلیکیشن خود بدهید وگرنه اپ شما کار نمیکند . 

مجوزها در فایل AndroidManifest تعریف میشود . 

مجوز زیر را بهش اضافه کنید : 

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

 

خب الان کتابخانه ی Retrofit و کتابخانه ی Gson نصب شده اند و مجوز اینترنت هم به اپ شما داده است . یعنی کاملا اماده است که کدنویسی کنید و ارتباط با سرور را برقرار کنید . 

 

شروع کار با Retrofit 

 یک نمونه یا instance از Retrofit بسازیم. موقتا این کار رو داخل Activity انجام می‌دیم. گرچه به یاد داشته باشید که اینکار درست نیست و روش درست‌ترش اینه که برای اپلیکیشن‌های بزرگ داخل کلاس Application تعریف بشه و یا بهتر از اون از Dagger استفاده بشه. ولی خوب فعلا سراغشون نمی‌ریم. این کدها با زبان جاوا است که از مبدل درون اندروید استودیو میتوانید آنها را به زبان جدید کاتلین نیز تبدیل کنید

 

public class MainActivity extends AppCompatActivity {
	Retrofit retrofit;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		retrofit = new Retrofit.Builder().build(); // فعلا به همین صورت ساده بسنده می‌کنیم.
		}
}

 

خب حالا برای اینکه بتونیم بصورت GET یک سری داده ها را از یک API بخوانیم باید یک interface ایجاد کنیم . مثلا یک url ازمایشی پیدا کردم که یک سری پست را بصورت json ارائه میدهد و من برای خواندن آنها اینطوری کدنویسی میکنم : 

 

public interface MyApi {
   @GET("https://jsonplaceholder.typicode.com/posts")
   Call<List<Post>> getPosts();
}

 

در کد بالا متد GET داره میگه که بصورت get باید داده ها را بخوانی و بعد متد getPosts  مشخصه که میخاد پست ها را بخونه داخل Call را ببینید . نوشتیم List<post> اینجا مشخص میکنیم چیزی که برای ما از سمت سرور قراره بیاد یه سری پست هست . 

خب ما اینجا کلا داده هایی بصورت json دریافت کردیم که برای فهم و درک کردن آنها یا اصطلاحالا پارس کردن json های دریافتی باید از کتابخانه ی GSON استفاده کنیم . که ما Gson و Gson convertor را به همین منظور در مرحله ی قبلی نصب کردیم . 

یادتون باشه به Retrofit بگید که ما قصد داریم از Gson استفاده کنیم . کد زیر برای زمانی است که ما یک retrofit جدید میسازیم . درون متود oncreate ...

retrofit = new Retrofit.Builder()
    .addConverterFactory(GsonConverterFactory.create())
    .build();

 

حالا دیگه رتروفیت می‌فهمه که باید از Gson استفاده کنه. اینکه Gson چطوری این تبدیلات رو انجام میده هم مربوط به بحث دیگریه.

حالا نیاز داریم interfaceی که بالاتر ساختیم رو یه جوری به رتروفیت متصل کنیم. برای اینکار از کد زیر استفاده می‌کنیم.

MyApi myApi = retrofit.create(MyApi.class);

حالا که یک نمونه از کلاس MyApi رو داریم خیلی راحت میتونیم از متودهای داخلش استفاده کنیم.

myApi.getPosts().enqueue(new Callback<List<Post>>() {
	@Override
	public void onResponse(Call<List<Post>> call, Response<List<Post>> response) {
		List<Post> posts = response.body(); // اینجا خیلی راحت فهرست پست‌ها که توسط Gson ساخته شده رو در اختیار داریم
	}
	
	@Override
	public void onFailure(Call<List<Post>> call, Throwable t) {
		// این متود هم فقط زمانی فرخوانی می‌شه که به هر دلیلی کانکشن ما با مشکل روبرو بشه
	}
});

خوب احتمالا باید بدونید که تو اندروید اجرای عملیات شبکه نیاز به هیچ وجه نباید روی thread اصلی برنامه اجرا بشه. به همین دلیل ما از متود enqueue استفاده می‌کنیم که این مشکل ما رو حل میکنه یعنی کانکشن زدن و خوندن دیتا رو روی Background Thread انجام میده.

خب یک مثال کاربردی در زیر اورده ایم که با آن میتوانید یک پروژه  ساده برای برنامه نویسی موبایل پیاده سازی کنید و مباحث رتروفیت را یاد بگیرید . 

یک پروژه ی جدید ایجاد کنید و سپس سه خط زیر را به فایل Build.gradle از نوع Module شده و در بخش dependencies اضافه کنید و سپس sync را بزنید : 

compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.google.code.gson:gson:2.6.1'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'

وارد فایل AndroidManifest.xml شوید و مجوز اینترنت را حتما بدهید : 

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

 

باید یک کلاس Pojo همراه با Annotation درست کنیم تا gson یک مپ از کلیدهای json ما درست کند تا بتوان آنها را پارس کند پس یک فایل به نام Post ایجاد کنید و کدهای زیر را در آن قرار دهید.

 

package ir.avasam.model;
 
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
 
public class Post {
 
    @SerializedName("title")
    @Expose
    private String title;
    @SerializedName("body")
    @Expose
    private String body;
    @SerializedName("userId")
    @Expose
    private Integer userId;
    @SerializedName("id")
    @Expose
    private Integer id;
 
    public String getTitle() {
        return title;
    }
 
    public void setTitle(String title) {
        this.title = title;
    }
    
    public String getBody() {
        return body;
    }
 
    public void setBody(String body) {
        this.body = body;
    }
 
    public Integer getUserId() {
        return userId;
    }
 
    public void setUserId(Integer userId) {
        this.userId = userId;
    }
 
    public Integer getId() {
        return id;
    }
 
    public void setId(Integer id) {
        this.id = id;
    }
     
    @Override
    public String toString() {
        return "Post{" +
                "title='" + title + '\'' +
                ", body='" + body + '\'' +
                ", userId=" + userId +
                ", id=" + id +
                '}';
    }
}

بعد از اینکار باید یک Instance از Retrofit بسازیم تا عمل Request زدن را ایجاد کند.

package ir.avasam;

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;
    }
}

بعد از اینکار باید APIService را ایجاد کنید ، این کلاس شامل متدهای مربوط به درخواست HTTP سمت سرور است مثل POST PUT GET DELETE و ...

پس یک فایل به نام APIService.java ایجاد کنید و کدهای زیر را در آن قرار دهید .  

package ir.avasam;

import com.chikeandroid.retrofittutorial2.data.model.Post;
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
 
public interface APIService {
 
    @POST("/posts")
    @FormUrlEncoded
    Call<Post> savePost(@Field("title") String title,
                        @Field("body") String body,
                        @Field("userId") long userId);
}

کد بالا یک  سری از مقادیری را به یک url خاص POST می کند نام متد را برابر با savePost قرار دادیم . 

در نهایت داده به این آدرس POST می شود : 

http://jsonplaceholder.typicode.com/posts

ما در حال استفاده از یک Api دمو از و آماده ی اینترنتی برای تست کردن رتروفیت و اپلیکیشن اندرویدی خودمان هستیم . 

و درنهایت یک کلاس به نام ApiUtils داریم که با فراخوانی آن عمل ارسال Request انجام  میگردد 

پس یک کلاس به نام ApiUtils.java ایجاد کنید و کدهای زیر را در آن قرار دهید : 

package ir.avasam;
 
public class ApiUtils {
 
    private ApiUtils() {}
 
    public static final String BASE_URL = "http://jsonplaceholder.typicode.com/";
 
    public static APIService getAPIService() {
 
        return RetrofitClient.getClient(BASE_URL).create(APIService.class);
    }
}

تا اینجا هرچیزی که برای Retrofit لازم بوده را ایجاد کردیم و حالا رتروفیت قابل استفاده میباشد . 

یک layer درست کنید و کدهای زیر را در آن قرار دهید مثلا : activity_main.xml 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_post"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        android:paddingBottom="@dimen/activity_vertical_margin"
        tools:context="com.chikeandroid.retrofittutorial2.AddEditPostActivity">
 
    <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:textAppearance="@style/TextAppearance.AppCompat.Title"
            android:text="AVASAM.IR"/>
    <EditText
            android:id="@+id/et_title"
            android:layout_marginTop="18dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/hint_title"/>
 
    <EditText
            android:id="@+id/et_body"
            android:lines="4"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/hint_body"/>
 
    <Button
            android:id="@+id/btn_submit"
            android:layout_marginTop="18dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorAccent"
            android:textColor="@android:color/white"
            android:text="@string/action_submit"/>
 
    <TextView
            android:id="@+id/tv_response"
            android:layout_marginTop="35dp"
            android:visibility="gone"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
     
</LinearLayout>

و در آخر کدهای درون MainActivity.java را نیز بصورت زیر مینویسیم : 

private TextView mResponseTv;
private APIService mAPIService;
 
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
 
    final EditText titleEt = (EditText) findViewById(R.id.et_title);
    final EditText bodyEt = (EditText) findViewById(R.id.et_body);
    Button submitBtn = (Button) findViewById(R.id.btn_submit);
    mResponseTv = (TextView) findViewById(R.id.tv_response);
 
    mAPIService = ApiUtils.getAPIService();
 
    submitBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            String title = titleEt.getText().toString().trim();
            String body = bodyEt.getText().toString().trim();
            if(!TextUtils.isEmpty(title) && !TextUtils.isEmpty(body)) {
                sendPost(title, body);
            }
        }
    });
}
public void sendPost(String title, String body) {
mAPIService.savePost(title, body, 1).enqueue(new Callback<Post>() {
    @Override
    public void onResponse(Call<Post> call, Response<Post> response) {
 
        if(response.isSuccessful()) {
            showResponse(response.body().toString());
            Log.i(TAG, "post submitted to API." + response.body().toString());
        }
    }
 
    @Override
    public void onFailure(Call<Post> call, Throwable t) {
        Log.e(TAG, "Unable to submit post to API.");
    }
});
}
 
public void showResponse(String response) {
    if(mResponseTv.getVisibility() == View.GONE) {
        mResponseTv.setVisibility(View.VISIBLE);
    }
    mResponseTv.setText(response);
}

 

ابتدا شئی ها را find کردیم بعد از اینکار دو متد نوشتیم متد اول sendPost برای ارسال یا Post اطلاعات است و متد دوم showResponse در صورتی که response درستی از سمت سرور دریافت شود داده را دریافت کرده و نمایش میدهد در بالا ApiUtils هم باعث اجرای درخواست می شود.

 

این آموزش به اتمام رسید موفق و پیروز باشید 

 

.

لینک کوتاه این مقاله : https://avasam.ir/post/113
این سیستم برپایه ی علاقه مندی شما یک دوره ی مناسب به شما پیشنهاد میدهد
مرا بسوی بهترین دوره ی آموزشی که برای من مناسب است هدایت کن 🤖
برای استفاده ی دیگران و حمایت از ما در جامعه های زیر به اشتراک بگذارید

.:: نظرهای کاربران ::.
مهمان / 3 سال پیش

سلام 

چطور میتونم یک فایل جیسون اماده رو تو لیست نمایش بدم و هر ایتم این لیست حاوی متنی باشه که توtitle هستش و عکسی که در url هستش رو نمایش بده لطفا راهنمای کنید

EhsanFallahi / 4 سال پیش
آموزشتون خیلی عالی و کامل بود....ممنون.
دوره ی آموزش پروژه محور ساخت کافه بازار دوره ی آموزش پروژه محور ساخت فروشگاه دیجیکالا آموزش لاراول دوره ی آموزش ویو جی اس