构建一个在内部使用Retrofit的库,包装响应 [英] Building a library that uses Retrofit internally, wrapping responses

查看:149
本文介绍了构建一个在内部使用Retrofit的库,包装响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建一个基本上包装我们api的库。基本上,我想要的结构是这样的:

I'm trying to build a library that basically wraps our api. Basically, the structure im going for is something like this:

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

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

//on response
//on failure

});

因此,对于vanilla Retrofit,api调用通常类似于以下内容:

So with vanilla Retrofit, an api call usually looks something like the following:

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返回的数据。

Basically, how would I wrap retrofits callback system into my own? Note, the reason for needing to do this is to preprocess the data returned from the api before delivering the final response.

推荐答案

I我写了类似的东西,所以它可能会帮助你入门,这是我为Volley编写的一个实现,并在我迁移到Retrofit2时重新使用,因此它类似于它(这个问题)。

I've written something similar so it might help you getting started, this follows an implementation I'v written for Volley, and re-used when I migrated to Retrofit2 so it resembles it (this SO question).

创建一个全局对象(你会称之为MySDK)作为处理你的请求的singelton类:

Create a global object (what you would refer to as MySDK) as a singelton class that handles your requests:

创建一个单独的类,你可以在你实例化时进行实例化重新申请出现:

create a singleton class, which you instatiate when you're application comes up:

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可能没有参数):

This works with your interface (example with POST and GET request, GET could be without params):

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

 //...

}

回调的简单监听器接口(单独的文件会很好):

a simple listener interface for your callback (seperate file would do good):

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

最后,从你想要的任何地方,上下文已经在那里,只是致电:

and finally, from wherever you want, the context is already in there, just call:

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等),只需记住需要在方法之间匹配的对象。

you can use any object with the listener, just parse the response string to a corresponding object, depending on what you need to receive and you can call that from everywhere (onClicks, etc.), just remember the objects need to match between methods.

希望这有帮助!

这篇关于构建一个在内部使用Retrofit的库,包装响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆