Использование Retrofit в Android
У меня есть приложение для Android, в котором есть 3 действия :
- Вход в систему
- Функциональность задач, в которой отображаются все задачи, относящиеся к пользователю (заполняются с помощью адаптера массива)
- Действие task_details, возникающее в результате щелчка по задаче в списке
Я должен использовать REST API. Исследование, которое я провел до сих пор, подсказывает мне использовать Retrofit. Я проверил, как его использовать, и обнаружил, что :
- Установите базовый URL-адрес в основном действии (мое действие - это действие входа в систему)
- Мне нужно создать класс API и определить свои функции с помощью аннотаций.
- Используйте адаптер класса Rest в Activity и определите обратные вызовы.
Если бы мое приложение было приложением для одного действия, я бы переработал все в своем приложении MainActivity.java но я не знаю, как и куда поместить весь код из шагов 1,2,3 для использования в моих трех действиях.Не могли бы вы помочь, рассказав, как использовать Retrofit в моем приложении. Большое спасибо.
В частности, мне нужны сетевые вызовы для: 1. Входа пользователя в систему 2. Получения всех задач пользователя. И для обоих я бы использовал данный REST api.
*********************************************
Calling Api USing Retrofit
*********************************************
**Dependancies** :-
implementation 'com.android.support:recyclerview-v7:27.1.1'
implementation 'com.squareup.picasso:picasso:2.5.2'
implementation 'com.android.support:cardview-v7:27.1.1'
enter code here
**Model**
use the Pozo class
**Api Call**
-> getLogin() // use the method
//API call for Login
private void getLogin()
{
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
AsyncHttpClient client = new AsyncHttpClient();
RequestParams requestParams = new RequestParams();
requestParams.put("email_id", edit_email.getText().toString());
requestParams.put("password", edit_password.getText().toString());
Log.e("", "LOGIN URL==>" + Urls.LOGIN + requestParams);
Log.d("device_token", "Device_ Token" + FirebaseInstanceId.getInstance().getToken());
client.post(Urls.LOGIN, requestParams, new JsonHttpResponseHandler() {
@Override
public void onStart() {
super.onStart();
ShowProgress();
}
@Override
public void onFinish() {
super.onFinish();
Hideprogress();
}
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
super.onSuccess(statusCode, headers, response);
Log.e("", "Login RESPONSE-" + response);
Login login = new Gson().fromJson(String.valueOf(response), Login.class);
edit_email.setText("");
edit_password.setText("");
if (login.getStatus().equals("true")) {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
MDToast mdToast = MDToast.makeText(SignInActivity.this, String.valueOf("User Login Successfully!"),
MDToast.LENGTH_SHORT, MDToast.TYPE_SUCCESS);
mdToast.show();
Utils.WriteSharePrefrence(SignInActivity.this, Util_Main.Constant.EMAIL, login.getData().getEmailId());
Utils.WriteSharePrefrence(SignInActivity.this, Constant.USERID, login.getData().getId());
Utils.WriteSharePrefrence(SignInActivity.this, Constant.USERNAME, login.getData().getFirstName());
Utils.WriteSharePrefrence(SignInActivity.this, Constant.PROFILE, login.getData().getProfileImage());
hideKeyboard(SignInActivity.this);
Intent intent = new Intent(SignInActivity.this, DashboardActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
} else {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
MDToast mdToast = MDToast.makeText(SignInActivity.this, String.valueOf("Login Denied"),
MDToast.LENGTH_SHORT, MDToast.TYPE_ERROR);
mdToast.show();
}
}
@Override
public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
super.onFailure(statusCode, headers, responseString, throwable);
Log.e("", throwable.getMessage());
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
MDToast mdToast = MDToast.makeText(SignInActivity.this, "Something went wrong",
MDToast.LENGTH_SHORT, MDToast.TYPE_ERROR);
mdToast.show();
}
});
}
Переведено автоматически
Ответ 1
Использование Retrofit довольно простое и понятное.
Прежде всего, вам нужно добавить retrofit в ваш проект, как, например, в системе сборки Gradle.
compile 'com.squareup.retrofit:retrofit:1.7.1' |
другим способом вы можете загрузить файл .jar и поместить его в свою папку libs.
Затем вам нужно определить интерфейсы, которые будут использоваться Retrofit для выполнения вызовов API к вашим конечным точкам REST. Например, для пользователей:
public interface YourUsersApi {
//You can use rx.java for sophisticated composition of requests
@GET("/users/{user}")
public Observable<SomeUserModel> fetchUser(@Path("user") String user);
//or you can just get your model if you use json api
@GET("/users/{user}")
public SomeUserModel fetchUser(@Path("user") String user);
//or if there are some special cases you can process your response manually
@GET("/users/{user}")
public Response fetchUser(@Path("user") String user);
}
ОК. Теперь вы определили свой интерфейс API и можете попробовать его использовать.
Для начала вам нужно создать экземпляр RestAdapter и задать базовый URL вашего серверного интерфейса API. Это также довольно просто:
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://yourserveraddress.com")
.build();
YourUsersApi yourUsersApi = restAdapter.create(YourUsersApi.class);
Here Retrofit will read your information from interface and under the hood it will create RestHandler according to meta-info your provided which actually will perform HTTP requests.
Then under the hood, once response is received, in case of json api your data will be transformed to your model using Gson library so you should be aware of that fact that limitations that are present in Gson are actually there in Retrofit.
Чтобы расширить / переопределить процесс сериализации / десериализации ваших данных ответа для ваших моделей, вы можете захотеть предоставить свои пользовательские сериализаторы / десериализаторы для retrofit.
Здесь вам нужно реализовать интерфейс конвертера и реализовать 2 метода FromBody() и toBody().
Вот пример:
public class SomeCustomRetrofitConverter implements Converter {
private GsonBuilder gb;
public SomeCustomRetrofitConverter() {
gb = new GsonBuilder();
//register your cursom custom type serialisers/deserialisers if needed
gb.registerTypeAdapter(SomeCutsomType.class, new SomeCutsomTypeDeserializer());
}
public static final String ENCODING = "UTF-8";
@Override
public Object fromBody(TypedInput body, Type type) throws ConversionException {
String charset = "UTF-8";
if (body.mimeType() != null) {
charset = MimeUtil.parseCharset(body.mimeType());
}
InputStreamReader isr = null;
try {
isr = new InputStreamReader(body.in(), charset);
Gson gson = gb.create();
return gson.fromJson(isr, type);
} catch (IOException e) {
throw new ConversionException(e);
} catch (JsonParseException e) {
throw new ConversionException(e);
} finally {
if (isr != null) {
try {
isr.close();
} catch (IOException ignored) {
}
}
}
}
@Override
public TypedOutput toBody(Object object) {
try {
Gson gson = gb.create();
return new JsonTypedOutput(gson.toJson(object).getBytes(ENCODING), ENCODING);
} catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
}
private static class JsonTypedOutput implements TypedOutput {
private final byte[] jsonBytes;
private final String mimeType;
JsonTypedOutput(byte[] jsonBytes, String encode) {
this.jsonBytes = jsonBytes;
this.mimeType = "application/json; charset=" + encode;
}
@Override
public String fileName() {
return null;
}
@Override
public String mimeType() {
return mimeType;
}
@Override
public long length() {
return jsonBytes.length;
}
@Override
public void writeTo(OutputStream out) throws IOException {
out.write(jsonBytes);
}
}
}
И теперь вам нужно включить ваши пользовательские адаптеры, если это было необходимо, используя setConverter() при сборке RestAdapter
ОК. Теперь вы знаете, как вы можете передавать свои данные с сервера в свое приложение для Android. Но вам нужно как-то управлять своими данными и вызывать вызов REST в нужном месте. Там я бы предложил использовать Android Service, или AsyncTask, или loader, или rx.java который запрашивал бы ваши данные в фоновом потоке, чтобы не блокировать ваш пользовательский интерфейс.
Итак, теперь вы можете найти наиболее подходящее место для вызова
SomeUserModel yourUser = yourUsersApi.fetchUser("someUsers")
для извлечения ваших удаленных данных.
Ответ 2
Я использовал retrofit всего пару недель, и сначала мне было трудно использовать его в своем приложении. Я хотел бы поделиться с вами самым простым способом использования retrofit в вашем приложении. И позже, если вы уже хорошо разбираетесь в retrofit, вы можете улучшить свои коды (отделив пользовательский интерфейс от api и используя обратные вызовы) и, возможно, позаимствовать некоторые приемы из поста выше.
В вашем приложении у вас есть логин, действие для списка задач и действие для просмотра подробной задачи.
Первым делом вам нужно добавить retrofit в ваше приложение, и есть 2 способа, следуйте сообщению @artemis выше.
Retrofit использует interface в качестве вашего API. Итак, создайте класс interface.
public interface MyApi{
/*LOGIN*/
@GET("/api_reciever/login") //your login function in your api
public void login(@Query("username") String username,@Query("password") String password,Callback<String> calback); //this is for your login, and you can used String as response or you can use a POJO, retrofit is very rubust to convert JSON to POJO
/*GET LIST*/
@GET("/api_reciever/getlist") //a function in your api to get all the list
public void getTaskList(@Query("user_uuid") String user_uuid,Callback<ArrayList<Task>> callback); //this is an example of response POJO - make sure your variable name is the same with your json tagging
/*GET LIST*/
@GET("/api_reciever/getlistdetails") //a function in your api to get all the list
public void getTaskDetail(@Query("task_uuid") String task_uuid,Callback<Task> callback); //this is an example of response POJO - make sure your variable name is the same with your json tagging
}
Создайте другой класс интерфейса для хранения всех ваших БАЗОВЫХ АДРЕСОВ вашего api
public interface Constants{
public String URL = "www.yoururl.com"
}
При входе в систему создайте метод для обработки модификации
private void myLogin(String username,String password){
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(Constants.URL) //call your base url
.build();
MyApi mylogin = restAdapter.create(MyApi.class); //this is how retrofit create your api
mylogin.login(username,password,new Callback<String>() {
@Override
public void success(String s, Response response) {
//process your response if login successfull you can call Intent and launch your main activity
}
@Override
public void failure(RetrofitError retrofitError) {
retrofitError.printStackTrace(); //to see if you have errors
}
});
}
В вашем MainActivityList
private void myList(String user_uuid){
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(Constants.URL) //call your base url
.build();
MyApi mytask = restAdapter.create(MyApi.class); //this is how retrofit create your api
mytask.getTaskDetail(user_uuid,new Callback<Task>>() {
@Override
public void success(ArrayList<Task> list, Response response) {
//process your response if successful load the list in your listview adapter
}
@Override
public void failure(RetrofitError retrofitError) {
retrofitError.printStackTrace(); //to see if you have errors
}
});
}
В вашем подробном списке
private void myDetailed(String task_uuid){
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(Constants.URL) //call your base url
.build();
MyApi mytask = restAdapter.create(MyApi.class); //this is how retrofit create your api
mytask.getTaskList(task_uuid,new Callback<Task>() {
@Override
public void success(Task task, Response response) {
//process your response if successful do what you want in your task
}
@Override
public void failure(RetrofitError retrofitError) {
retrofitError.printStackTrace(); //to see if you have errors
}
});
}
Надеюсь, это поможет вам, хотя это действительно самый простой способ использовать retrofit.
Ответ 3
Взгляните на этот отличный блог об использовании Retrofit в сочетании с Otto, обе библиотеки от Square.
http://www.mdswanson.com/blog/2014/04/07/durable-android-rest-clients.html
Основная идея заключается в том, что вы будете хранить ссылку на объект "репозитория" в вашем классе приложения. У этого объекта будут методы, которые "подписываются" на запросы событий rest api. Когда один из них будет получен, он выполнит соответствующий вызов Retrofit, а затем "опубликует" ответ, на который затем может быть "подписан" другой компонент (например, действие, отправившее запрос).
После правильной настройки всего этого доступ к данным через rest api становится очень простым. Например, выполнение запроса are на данные будет выглядеть примерно так :
mBus.post(new GetMicropostsRequest(mUserId));
и использование данных будет выглядеть примерно так:
@Subscribe
public void onGetUserProfileResponse(GetUserProfileResponse event) {
mView.setUserIcon("http://www.gravatar.com/avatar/" + event.getGravatar_id());
mView.setUserName(event.getName());
}
Требуется немного предварительных усилий, но в конце концов становится "тривиальным" доступ ко всему, что вам нужно, из нашего бэкенда через Rest.
Ответ 4
Вы можете попробовать сохранить ссылки на свой api внутри своего класса приложения. Затем вы можете получить его экземпляр из любого действия или фрагмента и получить api оттуда. Это звучит немного странно, но это может быть простой альтернативой DI. И если вы будете хранить ссылки только в своем классе приложения, это не будет своего рода объектом god
UPD: http://square.github.io/retrofit / - вот некоторая документация, она может быть полезна