Создание библиотеки, которая использует Retrofit внутри, обертывание ответов

Я пытаюсь создать библиотеку, которая в основном обертывает наш API. В основном, структура, которую я ищу, выглядит примерно так:

MySDK mySDK = new MySDK("username", "password");

mySDK.getPlaylistInfo("3423", 2323, new CustomCallback<>(){

//on response
//on failure

});

Итак, с vanilla Retrofit вызов API обычно выглядит примерно так:

ApiService api = retrofit.create(ApiService.class);
Call<Response> call = api.getPlaylistInfo()
call.enqueue(new Callback<Response>() {
    @Override
    public void onResponse(Call<Response> call, Response<Response> response) {
        //handle response
    }

    @Override
    public void onFailure(Call<Response> call, Throwable t) {
        //handle failure
    }

});

По сути, как бы я перенес модернизированную систему обратного вызова в свою собственную? Обратите внимание, что это необходимо сделать для предварительной обработки данных, возвращаемых API, перед доставкой окончательного ответа.


person Orbit    schedule 02.05.2016    source источник


Ответы (1)


Я написал что-то подобное, так что это может помочь вам начать работу, это следует за реализацией, которую я написал для Volley, и повторно использовал, когда я перешел на Retrofit2, поэтому он похож на него (это ТАК вопрос).

Создайте глобальный объект (то, что вы бы назвали MySDK) как класс синглтона, который обрабатывает ваши запросы:

создайте одноэлементный класс, который вы устанавливаете, когда появляется ваше приложение:

public class NetworkManager
{
    private static final String TAG = "NetworkManager";
    private static NetworkManager instance = null;

    private static final String prefixURL = "http://some/url/prefix/";

    //for Retrofit API
    private Retrofit retrofit;
    private ServicesApi serviceCaller;

    private NetworkManager(Context context)
    {
        retrofit = new Retrofit.Builder().baseUrl(prefixURL).build();
        serviceCaller = retrofit.create(ServicesApi.class);
        //other stuf if you need
    }

    public static synchronized NetworkManager getInstance(Context context)
    {
        if (null == instance)
            instance = new NetworkManager(context);
        return instance;
    }

    //this is so you don't need to pass context each time
    public static synchronized NetworkManager getInstance()
    {
        if (null == instance)
        {
            throw new IllegalStateException(NetworkManager.class.getSimpleName() +
                    " is not initialized, call getInstance(...) first");
        }
        return instance;
    }

    public void somePostRequestReturningString(Object param1, final SomeCustomListener<String> listener)
    {
        String url = prefixURL + "this/request/suffix";

        Map<String, Object> jsonParams = new HashMap<>();
        jsonParams.put("param1", param1);

        Call<ResponseBody> response;
        RequestBody body;

        body = RequestBody.create(okhttp3.MediaType.parse(JSON_UTF), (new JSONObject(jsonParams)).toString());
        response = serviceCaller.thePostMethodYouWant("someUrlSufix", body);

        response.enqueue(new Callback<ResponseBody>()
        {
            @Override
            public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> rawResponse)
            {
                try
                {
                  String response = rawResponse.body().string();

                  // do what you want with it and based on that...
                  //return it to who called this method
                  listener.getResult("someResultString");
                }
                catch (Exception e)
                {
                 e.printStackTrace();
                 listener.getResult("Error1...");
                }
            }  
            @Override
            public void onFailure(Call<ResponseBody> call, Throwable throwable)
            {
                try
                {
                 // do something else in case of an error
                 listener.getResult("Error2...");
                }
                catch (Exception e)
                {
                 throwable.printStackTrace();
                 listener.getResult("Error3...");
                }
            }
        });
    }

    public void someGetRequestReturningString(Object param1, final SomeCustomListener<String> listener)
    {
        // you need it all to be strings, lets say id is an int and name is a string
        Call<ResponseBody> response = serviceCaller.theGetMethodYouWant
            (String.valueOf(param1.getUserId()), param1.getUserName());

        response.enqueue(new Callback<ResponseBody>()
        {
            @Override
            public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> rawResponse)
            {
                try
                {
                  String response = rawResponse.body().string();

                  // do what you want with it and based on that...
                  //return it to who called this method
                  listener.getResult("someResultString");
                }
                catch (Exception e)
                {
                 e.printStackTrace();
                 listener.getResult("Error1...");
                }
            }  
            @Override
            public void onFailure(Call<ResponseBody> call, Throwable throwable)
            {
                try
                {
                // do something else in case of an error
                 listener.getResult("Error2...");
                }
                catch (Exception e)
                {
                 throwable.printStackTrace();
                 listener.getResult("Error3...");
                }
            }
        });
    }
}

Это работает с вашим интерфейсом (пример с запросом POST и GET, GET может быть без параметров):

 public interface BelongServicesApi
 {
    @POST("rest/of/suffix/{lastpart}") // with dynamic suffix example
    Call<ResponseBody> thePostMethodYouWant(@Path("lastpart") String suffix, @Body RequestBody params);

    @GET("rest/of/suffix") // with a fixed suffix example
    Call<ResponseBody> theGetMethodYouWant(@Query("userid") String userid, @Query("username") String username);
 }

когда появится ваше приложение:

public class MyApplication extends Application
{
  //...

    @Override
    public void onCreate()
    {
        super.onCreate();
        NetworkManager.getInstance(this);
    }

 //...

}

простой интерфейс слушателя для вашего обратного вызова (отдельный файл подойдет):

public interface SomeCustomListener<T>
{
    public void getResult(T object);
}

и, наконец, откуда хотите, контекст уже есть, просто вызовите:

public class BlaBla
{
    //.....

        public void someMethod()
        {
            //use the POST or GET 
            NetworkManager.getInstance().somePostRequestReturningString(someObject, new SomeCustomListener<String>()
            {
                @Override
                public void getResult(String result)
                {
                    if (!result.isEmpty())
                    {
                     //do what you need with the result...
                    }
                }
            });
        }
}

вы можете использовать любой объект со слушателем, просто проанализируйте строку ответа на соответствующий объект, в зависимости от того, что вам нужно получить, и вы можете вызывать это из любого места (onClicks и т. д.), просто помните, что объекты должны соответствовать между методами.

Надеюсь это поможет!

person TommySM    schedule 09.05.2016