简体   繁体   English

如何使用Retrofit 2在Android中将应用程序逻辑与网络层分开

[英]How to separate application logic from network layer in Android using Retrofit 2

I am new in Android and Retrofit and I am facing one problem. 我是Android和Retrofit的新手,我遇到了一个问题。

I want to have my lets say "ServerCommunication" class (singelton) where all Retrofit magic is done and it will have public methods where REST calls are done. 我想让我的让我们说“ServerCommunication”类(singelton),其中所有的Retrofit魔法都已完成,并且它将具有完成REST调用的公共方法。

I want to use this "ServerCommunication" instance in my activities to call Rest service, but thats it. 我想在我的活动中使用这个“ServerCommunication”实例来调用Rest服务,但就是这样。 Application logic should be done in activity. 应用程序逻辑应该在活动中完成。 So this way some activity Login calls method Login(POJORequest) in "ServerCommunication) where actual REST call via Retrofit framework is done and some POJOResponse is returned. So Activity doesn't care about REST communication while ServerCommunication doesn't care about what logic that should be applied to response from REST service since. 所以这样一些活动Login调用方法Login(POJORequest)在“ServerCommunication”中,通过Retrofit框架完成实际的REST调用并返回一些POJOResponse。所以Activity不关心REST通信,而ServerCommunication不关心什么逻辑应该应用于REST服务的响应。

With retrofit 2 I do not understand how I can block Activity to wait for response from retrofit and how it can be returned. 通过改造2,我不明白如何阻止Activity等待改造的响应以及如何返回。 Well, I might think I can use some callback methods in activity so those methods can be called from ServerCommunication" in OnPostExecute() to apply some logic based on data from response. It's just I think it should be simpler approach. 好吧,我可能认为我可以在活动中使用一些回调方法,因此可以从OnPostExecute()中的ServerCommunication调用这些方法,以根据响应中的数据应用一些逻辑。我认为这应该是更简单的方法。

Well, to clarify all this mess above imagine simple case: You have data in you main activity, you pass this data to your communication class where REST call is done and response is received. 好吧,为了澄清上面的所有混乱,想象一下简单的情况:你在主要活动中有数据,你将这些数据传递给完成REST调用并收到响应的通信类。 This response must be validated in order to continue. 必须验证此响应才能继续。 And you want this validation to be done in main activity and NOT in communication class. 并且您希望此验证在主要活动中完成,而不是在通信类中完成。

What is pattern to do that in Android with Retrofit2 ? 使用Retrofit2在Android中执行此操作的模式是什么?

Thank you in advance 先感谢您

What I normally do: 我通常做的事情:

  • Create your Interface (where you have all your REST methods - GET & POST etc) 创建您的界面(您拥有所有REST方法 - GET和POST等)
  • Create a class that does the actual calls with corresponding methods (refer to the interface REST methods). 创建一个使用相应方法执行实际调用的类(请参阅接口REST方法)。 I would call it something like ServiceAPIImplementor. 我会称之为ServiceAPIImplementor。 This is where you actually create your Retrofit adapter. 这是您实际创建Retrofit适配器的地方。
  • In your activity, create an instance of your implementor class and call the methods and pass the expected arguments. 在您的活动中,创建实现者类的实例并调用方法并传递预期的参数。
  • After calling the methods, you should probably show a progress dialog to let the user know that something is going on. 在调用方法之后,您应该显示一个进度对话框,让用户知道某些事情正在发生。
  • When the onResponse or onFailure method is called, use an Event pattern (EventBus library?) to notify the activity that the network operation has been completed. 调用onResponseonFailure方法时,使用事件模式(EventBus库?)通知活动网络操作已完成。 Once the activity has received the notification, it should then dismiss the progress dialog and update the UI accordingly - with the newly received data or completed operation (expected outcome). 一旦活动收到通知,它就应该关闭进度对话框并相应地更新UI - 使用新接收的数据或完成的操作(预期结果)。

I hope this helps you get closer to what you are trying to achieve! 我希望这可以帮助您更接近您想要实现的目标!

Service interface (IPhotoService): 服务接口(IPhotoService):

@GET("/photos/kudos")
Call<String> fetchKudos(@Header("Authorization") String authorization,
                        @Query("offset") int offset, @Query("mt") boolean mt);

Service impl (PhotoService): 服务impl(PhotoService):

private GoApiProvider<IPhotoService> mGoProvider = new GoApiProvider<>();

public Promiser<List<Photo>, HttpError> fetchKudos() {
    return new Promiser<>((resolve, reject) ->
            mGoProvider.getService(IPhotoService.class).fetchKudos(mSession.getToken(),
                    mOffsetKudos, true).enqueue(new Callback<String>() {
                @Override
                public void onResponse(Call<String> call, Response<String> response) {
                    if (response.isSuccessful()) {
                        PhotoParser JSON = new PhotoParser();
                        try {
                            mOffsetKudos = mOffsetKudos + 20;
                            resolve.run(JSON.photosFromJson(response.body()));
                        } catch (JSONException e) {
                            Log.e("fetchKudos", e.toString());
                        }
                    } else {
                        reject.run(new HttpError(response.code(), response.message()));
                    }
                }

                @Override
                public void onFailure(Call<String> call, Throwable t) {
                    reject.run(new HttpError(YPErrorType.Undefined.getType(), t.getMessage()));
                }
            })
    );
}

Activity or Fragment : 活动或片段:

private void loadPhoto() {
    new PhotoService().fetchKudos()
            .success(this::resultSucceeded)
            .error(this::resultError);
}

private void resultSucceeded(List<Photo> photos) {
    mPhotoAdapter.setItems(photos);
}

private void resultError(HttpError httpError) {
    httpErrorToast(httpError);
}

If you want to use Promizer: Click here 如果你想使用Promizer: 点击这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM