2015-07-09 5 views
1

Я делаю приложение для Android, которое подключается к веб-сервису через REST API, и у меня есть дилемма с дизайном внутренней архитектуры.Лучший способ моделирования соединения Android REST

Теперь у меня есть класс Client.java которого purpouse это сделать соединение с сервером (ConnectionMethod является Enum, который содержит GET | значения POST):

public class Client { 
private AsyncHttpClient client = new AsyncHttpClient(); //I use com.loopj.AsyncHttpClient to connect 
private ConnectionMethod method; 
private RequestParams params = new RequestParams(); 
private AsyncHttpResponseHandler responseHandler = new JsonHttpResponseHandler(){ 
    @Override 
    public void onSuccess(int statusCode, Header[] headers, JSONObject response) { 
     //Actions when connection success 
    } 
    @Override 
    public void onFailure(int statusCode, Header[] headers, JSONObject response, Throwable error) { 
     //Actions when connection fails 
    } 
}; 

public Client (RequestParams params, ConnectionMethod method) { 
    this.params = params; 
    this.method = method; 
} 

public void addParameters (Map<String, String> parameters) { 
    for (Map.Entry<String, String> entry : parameters.entrySet()) { 
     this.params.put(entry.getKey(), entry.getValue()); 
    } 
} 

public ServerResponse connect() { 
    RequestHandle handle; 

    if (this.method==ConnectionMethod.POST) { 
     handle = postRequest(); 
    } 
    else { 
     handle = getRequest(); 
    } 
    //How can I treat here different type of responses homogeneously? 
} 

private RequestHandle getRequest() { 
    return client.get(Constants.getEndpoint(), this.params, this.responseHandler); 
} 

private RequestHandle postRequest() { 
    return client.post(Constants.getEndpoint(), this.params, this.responseHandler); 
} 
} 

метод выборки, который запрашивает информацию от сервера заключается в следующем:

public static void login (String login, String password) { 
//This classes should be static or dynamic? 
    Map<String, String> map = new HashMap<String, String>(); 

    map.put("login", login); 
    map.put("password", password); 
    map.put("method", "site_login"); 

    Client c = new Client(); 
    c.addParameters(map); 
    c.getRequest(); 
} 

Все ответы сервера являются JSON: {статус: 0, результат: массив/INT/строка}, когда ответ является правильным и {статус: -1, сообщение: строка}, когда ответ неверен.

Дополнительная информация Я хочу сделать классы для моделирования компонентов из результата JSON (User.java, Message.java ...) и промежуточных методов между UI и API для реализации логики приложения и классов.

Каков наилучший способ создания однородной системы соединений, которая управляет автоматически правильным/отказоустойчивым ответом и не зависит от модели (пользователь, сообщение ...)?

+3

Не беспокойтесь, используйте Retrofit http://square.github.io/retrofit/ –

ответ

2

Вы описываете инструменты, которые уже существуют. Мой любимый - Retrofit, но есть и другие. Модернизация может справиться с успехами и сбойными ответами и даже сопоставить JSON напрямую с POJO.

Мой API клиент

public class ApiClient { 

private static ApiInterface sApiInterface; 

public static ApiInterface getApiClient(Context context) { 

    //build the rest adapter 
    if (sApiInterface == null) { 
     final RestAdapter restAdapter = new RestAdapter.Builder() 
       .setEndpoint("example.com") 
       .build(); 
     sApiInterface = restAdapter.create(ApiInterface.class); 
    } 
    return sApiInterface; 
} 


public interface ApiInterface { 

    @GET("/program/{id}") 
    void getProgram(@Path("id") int id, RetrofitCallback<Program> callback); 

} 

Мой RetrofitCallback

public class RetrofitCallback<S> implements Callback<S> { 
private static final String TAG = RetrofitCallback.class.getSimpleName(); 


@Override 
public void success(S s, Response response) { 

} 

@Override 
public void failure(RetrofitError error) { 
    Log.e(TAG, "Failed to make http request for: " + error.getUrl()); 
    Response errorResponse = error.getResponse(); 
    if (errorResponse != null) { 
     Log.e(TAG, errorResponse.getReason()); 
     if (errorResponse.getStatus() == 500) { 
      Log.e(TAG, "Handle Server Errors Here"); 
     } 
    } 
} 
} 

Моя модель

public class Program { 
@Expose 
private doublea.models.Airtime Airtime; 
@Expose 
private String id; 
@Expose 
private String title; 
@SerializedName("short_name") 
@Expose 
private String shortName; 
@SerializedName("full_description") 
@Expose 
private String fullDescription; 
@SerializedName("short_description") 
@Expose 
private String shortDescription; 
@Expose 
private doublea.models.Image Image; 
@SerializedName("image") 
@Expose 
private String imageName; 
@Expose 
private List<Host> hosts = new ArrayList<Host>(); 
@Expose 
private List<Category> categories = new ArrayList<Category>(); 
@Expose 
private List<Airtime> airtimes = new ArrayList<Airtime>(); 

/** Getters and Setters */ 

public Program() { 
} 

Как он используется.

private void executeProgramApiCall(int programId) { 
    ApiClient.getApiClient(this).getProgram(programId, new RetrofitCallback<Program>() { 

     @Override 
     public void success(Program program, Response response) { 
      super.success(program, response); 
      addDataToAdapter(program); 
     } 
    }); 
} 
5

Существует множество структур, которые могут облегчить весь этот процесс. Например, Retrofit - очень простая структура для сопоставления классов java для вызовов REST. Он поставляется с gson, который автоматически десериализует ответ от json на простые java-объекты.

Он также позволяет использовать обратные вызовы, а также наблюдаемые данные rxJava. Он также позволяет обрабатывать ошибки.

Вы можете проверить пример приложения: https://github.com/JakeWharton/u2020