آموزش رتروفیت ، به زبان ساده رتروفیت کتابخانه ای برای اتصال به سرور است که خیلی از کارها و ریزه کاری های اتصال رو خودش انجام میده و ما کافیه فقط درخواست رو سفارشی سازی و به سرور متصل کنیم.
رتروفیت با استفاده از دو مولفه اساسی نتیجه خیلی مطلوب تری خواهد داد که عبارتند از انوتیشن ها annotation و کلاس Gson برای تبدیل کردن رشته جیسون دریافتی به یک کلاس جاوا یا کاتلین تروتمیز !!
این نکته رو درنظر داشته باشید که ما در این آموزش هردو زبان جاوا و کاتلین رو آوردیم که طرفدارهای هردوزبان از ما راضی باشن ! 🙂
همچنین بخوانید: معماری mvp در اندروید با کاتلین
خب قبل از هر چیز بهتره که وابستگی کتابخانه رتروفیت retrofit رو به پروژه اضافه کنیم و بعد ادامه آموزش رتروفیت رو کار کنیم پس به صورت های زیر میتونید کتابخونه رتروفیت رو به پروژه خود ایمپورت کنید
Maven
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>retrofit</artifactId>
<version>2.5.0</version>
</dependency>
Gradle
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
دانلود فایل jar رتروفیت
انوتیشن ها (annotation) یا به عبارت فارسی حاشیه نوشت ها درواقع برای توصیف نوع درخواست ما و همچنین نگهدارنده ای برای پارامترهای ارسالی و یا Multipart request body (درخواست های چندپاره) ما هستند (نکته مهم اینکه هر درخواست رتروفیت باید با یک annotation مشخص شده باشد! )
دررتروفیت ما درکل پنج annotation برای مشخص کردن نوع درخواست رتروفیت داریم
GET, POST, PUT, DELETE, HEAD
که در ادامه هرکدام را به طور واضح توضیح خواهیم داد.
با انوتیشن @GET درخواست ما تبدیل به یک ریکوست رتروفیت دریافتی میشود بدین صورت که پارامتر ارسالی به سرور ندارد و فقط قصد گرفتن دیتاها را از سرور دارد
برای مثال در مثال زیر درخواست رتروفیت ما از نوع Get هستش و endpoint هم مقدار getUsers.php هستش
@GET("getUsers.php")
اما endPoint چیه؟!
خب آدرس درخواست ها در رتروفیت به دو بخش baseUrl یا آدرس پایه و endPoint یا نقطه انتهایی تقسیم میشن.
یعنی چی ؟
فرض کنید ما یک آدرس api بصورت زیر داریم
https://tejariapp.com/apis/getSomeUsers.php
خب مشخصا تا بخش tejariapp.com که دامنه هستش و تغییر نخواهد کرد
بخش apis هم احتمالا یک فولدر هست که api هارو داخلش قرار دادیم پس احتمال زیاد این بخش هم تغییر نخواهد کرد
اما قسمت اخر که getSomeUsers.php هست اسم api ما هستش و طبیعتا با بقیه api ها تفاوت داره
پس نتیجه ؟!
قسمت هایی از آدرس که برای تمام api های استفاده شده ثابت هستند به baseUrl درخواست رتروفیت تبدیل میشود
و قسمت هایی که برای هر درخواست رتروفیت متغیر است به endPoint تبدیل خواهد شد.
بخش endpoint درخواست رتروفیت داخل حاشیه نوشت ها یا annotation ها قرار میگیره و بخش baseUrl زمان ساخت ریکوست یا درخواست رتروفیت ایجاد میشه
نکته قابل توجه اینکه تمامی endPoint ها یا به اصطلاح تمامی درخواست ها داخل یک interface قرار میگیرن که با یک آبجکت رتروفیت میتونیم به این درخواست ها اشاره و هرکدام را فراخوانی کنیم
که درادامه مثال های متنوعی از آن خواهیم دید ک 😉
خب از بحث اصلی دور نشیم !
انوتیشن @POST این امکان را به ما میدهد که یک سری پارامتر یا داده نیز همراه با درخواست رتروفیت به api ارسال کنیم (بشدت پرکاربرد) برای مثال
@POST("createUser.php")
نکته: انوتیشن POST باید حتما یک انوتیشن دیگه با عنوان زیر بهش اضافه کنیم
@FormUrlEncoded
اما این annotation چیکار میکنه ؟!
خب ما میتونیم درخواست های رتروفیت خودمون رو به دوصورت زیر تقسیم کنیم(در مواقعی که میخوایم دیتا همراه با درخواست رتروفیت ارسال شه)
form-encoded
برای ارسال دیتا بصورت کلید -> مقدار
multipart data
آپلود دیتاهای حجیم مانند عکس و تصویر
که در نهایت درخواست رتروفیت ما بصورت زیر خواهد شد
@FormUrlEncoded
@POST("createUser.php")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
خب همونطور که میبینید ما یک سری پارامتر با انوتیشن@Field داریم پس یعنی درخواست ما جزو form-encoded هاست (کلید -> مقدار ) که کلید first_name و last_name و مقادیر همان متغیرهایی ست که مقادیرشان را ما زمان فراخوانی به آنها پاس میدهیم
ادامه بحث قبل ما متوجه شدیم که دو حالت ارسال داده به سرور داریم یکی داده های form-encoded و دیتاهای حجیم multipart
حالا میخوایم نمونه ای از درخواست رتروفیت رو برای داده های multipart ببینیم که با انوتیشن @P درخواست رو مشخص میکنیم
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
خب همونطور که میبینید ما از انوتیشن @Part برای مشخص کردن کلید و داده های حجیم استفاده کردیم
با استفاده از این انوتیشن نیز میتوان یک مقدار ثابت به عنوان header درخواست رتروفیت درنظر گرفت
× توضیح کوتاهی درباره header :
ما در header درخواست ها که از سمت کلاینت به سرور میروند اطلاعاتی درباره درخواست و یا درمورد داده هایی که در بدنه درخواست منتقل میشوند دراختیار سرور قرار میدهیم
ساختار ایجاد هدر برای درخواست ها نیز بصورت زیر است
Header-Name: value
برای مثال به اطلاعات هدر زیر دقت کنید
Host: tejariapp.com
Accept-Language: en-US,en;q=0.8,fa;q=0.6,es;q=0.4
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36
Accept: text/html,application/xhtml+xml, application/xml;q=0.9, image/webp,/;q=0.8
هدر اول نام مقصد درخواست است.
هدر دوم زبان استفاده شده است.
هدر سوم نشان دهنده ارسال کننده درخواست است برای مثال مرورگر موزیلا یا کروم
و هدر اخر نیز نشان دهنده نوع داده ریسپانس قابل قبول است.
اگر علاقه مند به هدر header ها و انواع آنها شدید پیشنهاد میکنم اینجا رو حتما کلیک کنید و انوع هدر هارو ببنید اما حتما برگردید و ادامه مقاله رو تا انتها بخونید 😀
/;q=0.8
هدر اول نام مقصد درخواست است.
هدر دوم زبان استفاده شده است.
هدر سوم نشان دهنده ارسال کننده درخواست است برای مثال مرورگر موزیلا یا کروم
و هدر اخر نیز نشان دهنده نوع داده ریسپانس قابل قبول است.
اگر علاقه مند به هدر header ها و انواع آنها شدید پیشنهاد میکنم اینجا رو حتما کلیک کنید و انوع هدر هارو ببنید اما حتما برگردید و ادامه مقاله رو تا انتها بخونید 😀
/;q=0.8
هدر اول نام مقصد درخواست است.
هدر دوم زبان استفاده شده است.
هدر سوم نشان دهنده ارسال کننده درخواست است برای مثال مرورگر موزیلا یا کروم
و هدر اخر نیز نشان دهنده نوع داده ریسپانس قابل قبول است.
اگر علاقه مند به هدر header ها و انواع آنها شدید پیشنهاد میکنم اینجا رو حتما کلیک کنید و انوع هدر هارو ببنید اما حتما برگردید و ادامه مقاله رو تا انتها بخونید 😀
و اما مثالی از درخواست رتروفیت با هدر
@Headers("Cache-Control: max-age=640000")
@GET("getUsers.php")
Call<List<Widget>> widgetList();
و اما بریم سراغ دستور call که در مثال های بالا زیاد دیدیم !
میتونیم اینطور بگیم که دستور call درواقع یک اینترفیس رتروفیت هستش که ریکوست یا درخواست های رتروفیت رو بصورت همگام Synchronously یا ناهمگام Asynchronously اجرا میکنه
برای اجرای درخواست بصورت ناهمگام باید از دستور زیر استفاده کنیم
void enqueue(Callback callback);
و برای اجرای همگام هم باید از دستور زیر استفاده کنیم
Response execute() throws IOException;
خب قطعا الان خیلی متوجه پاراگراف بالا نشدید ! در ادامه چند مثال برای ران کردن یک درخواست خواهیم زد که کاملا متوجه درخواست های رتروفیت بشید 🙂
خب بریم یک درخواست رتروفیت ایجاد کنیم
قدم اول اینکه بیس درخواست رتروفیت رو ایجاد کنیم
جاوا
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://tejariapp.com/")
.build();
کاتلین
val retrofit = Retrofit.Builder()
.baseUrl("https://tejariapp.com/")
.build()
یعنی چی ؟ یعنی اینکه یک آبجکت رتروفیت با همون baseUrl مدنظر (که در بالا کامل توضیح داده شد) ایجاد و build کنیم
سپس یک آبجکت برای اینترفیسی که endPoint ها داخلش هست ایجاد میکنیم
جاوا
TaskService service = retrofit.create(TaskService.class);
کاتلین
val service = retrofit.create(TaskService::class.java)
و حالا میتونیم یک درخواست ناهمگام بصورت زیر ایجاد کنیم
جاوا
service.usersList().enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
// success get some response
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
// failed response
}
});
کاتلین
service.usersList().enqueue(object : Callback<ResponseBody> {
override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
// success get some response
}
override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
// failed response
}
})
همونطور که میبینید ما از enqueue استفاده کردیم که این یعنی درخواست ما ناهمگام هستش
اما دو بلاک onResponse وonFailure ایجاد شده که مشخصا متد onResponse زمانی فراخوانی میشود که ما با موفقیت از درخواست رتروفیت ریسپانس دریافت کردیم
این متد دو پارامتر داره که call شامل اطلاعات درخواست و response شامل محتوی ریسپانس دریافتی ست نکته اینکه نوع این پارامتر دقیقا نوعی ست که برای endPoint خودمون درنظر گرفتیم
درواقع endPoint ما در اینترفیس TaskService بصورت زیر است
جاوا
@GET("getUsers.php")
Call<ResponseBody> usersList();
کاتلین
@GET("getUsers.php")
fun usersList(): Call<ResponseBody>
و اما بلاک onFailure طبیعتا زمانی اجرا میشه که درخواست به هردلیلی به مشکل خودره و نتونسته ریسپانسی از سرور بگیره
این متد هم دو پارامتر داره که call اطلاعات درخواست و t محتویات مشکل ریکوست رو داخل خودش داره ( پس طبیعتا اگر بخوایم متوجه بشیم که درخواست چرا به مشکل خورده باید مقدار پارامتر t رو بررسی کنیم )
و اما اگر بخوایم درخواست رتروفیت بصورت همگام اجرا بشه باید درخواست رو بصورت زیر تغییر بدیم
جاوا
try {
service.usersList().execute();
} catch (IOException e) {
e.printStackTrace();
}
کاتلین
try {
service.usersList().execute()
} catch (e: IOException) {
e.printStackTrace()
}
خب حالا ما تونستیم یک درخواست رتروفیت رو ایجاد کنیم و با سرور ارتباط برقرار کنیم حالا باید بتونیم داده هایی که گرفتیم که عموما در قالب json یا xml هستن رو به نوع قابل استفاده در زبان جاوا یا کاتلین تبدیل کنیم
که رتروفیت شش کتابخانه رو پیشنهاد داده که به شرح زیر هستن
Gson: com.squareup.retrofit2:converter-gson
Jackson: com.squareup.retrofit2:converter-jackson
Moshi: com.squareup.retrofit2:converter-moshi
Protobuf: com.squareup.retrofit2:converter-protobuf
Wire: com.squareup.retrofit2:converter-wire
Simple XML: com.squareup.retrofit2:converter-simplexml
Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars
همچنین بخوانید: آموزش کتابخانه Gson برای تبدیل جیسون در اندروید
ما (و البته خیلی های دیگه) از Gson استفاده میکنیم چون برای استفاده ساده س و پیچیدگی خاصی نداره و صد البته که کتابخانه قدرتمندیه و نیازهای مارو برطرف میکنه !
پس در پست بعدی بطور کامل با کتابخانه Gson آشنا خواهیم شد و مثال های زیادی را با هردو زبان جاوا و کاتلین خواهیم داشت 🙂
امیدوارم این آموزش رتروفیت برای شما مفید بوده باشد.
کلمات کلیدی: آموزش رتروفیت,آموزش Retrofit,آموزش رتروفیت در اندورید
4 Comments
BEST
آموزشتون عالیه.
فقط حیف که تا به تبدیل جیسون به جاوا رسید متوقف کردین!!
کد های نا به همگام رو کجا وارد کنیم ؟
با سلام
اگر منظورتون از درخواست های نا به همگام، همون درخواست های Asynchronously هستش، می تونید درخواست رو به صورت enqueue پیاده کنید و در هر قسمت از اپلیکیشن که نیاز به ارسال درخواست به api داره قرار بدید.
با احترام