Android 实现2服务接口
想象一下下面的场景 我将改型作为我的API客户机,并将使用缓存机制在本地(比如SQLite数据库)保存一些响应,因此一些数据只获得一次。为以下接口创建一个自定义实现似乎是一个完美的例子,该接口将在网络不可用时从本地数据库获取数据Android 实现2服务接口,android,retrofit,retrofit2,android-networking,Android,Retrofit,Retrofit2,Android Networking,想象一下下面的场景 我将改型作为我的API客户机,并将使用缓存机制在本地(比如SQLite数据库)保存一些响应,因此一些数据只获得一次。为以下接口创建一个自定义实现似乎是一个完美的例子,该接口将在网络不可用时从本地数据库获取数据 public interface CommentsService { @GET("posts/{postId}/comments") Call<List<Comment>> getCommentsOfPost(@Path("p
public interface CommentsService {
@GET("posts/{postId}/comments")
Call<List<Comment>> getCommentsOfPost(@Path("postId") int id);
}
公共接口评论服务{
@获取(“posts/{postId}/comments”)
调用getCommentsOfPost(@Path(“postId”)int-id);
}
问题在于,Refught2中的所有服务方法都应该包装在Call
对象中,因为它阻止回调作为参数传递,就像以前版本的Refught2一样
我想知道创建此接口的自定义实现是否是一种良好的做法,如果是,那么如何处理调用对象?在第2部分中,您可以使用
Call.enqueue(Callback)
来指定回调。比如说,
getCommentsService.getCommentsOfPost(myInt).enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
// do something with the response
}
}
如果您想要同步执行,请使用
Call.execute()
如果您有RxJava的经验,这将变得更容易,因为您可以在获取数据时组合多个任务,并尽快显示数据。因此,首先要做的是将api结果保存到数据库中。下次要显示数据时,可以调用concat方法连接多个源请求(来自缓存、磁盘或服务器),以尽快检索数据
这是一个很好的解释
因为您只想在网络不可用时检查本地数据库,所以您还可以实现一个回调接口,并将其作为参数传递给正在进行改装调用的函数。通过这种方式,您可以使函数返回为void,并且从改装调用的onResonse或onFailure方法内部,您可以决定是从成功响应(onResponse)还是从本地数据库(onFailure)加载,即对自定义接口的所需函数进行所需调用。这将在异步调用中模拟您的改装调用的同步行为,同时使您能够灵活地做出决策,即使您收到不正确的响应。如果我正确理解您的问题,您希望从SQLite获取数据,以防没有网络连接 您可以使用此接口定义端点:
public interface CommentsService {
@GET("posts/{postId}/comments")
Call<List<Comment>> getCommentsOfPost(@Path("postId") int id);
}
其中CommentsServiceResultListener是传递给前一个接口实现的侦听器。我们将其定义如下:
public interface CommentsServiceResultListener {
void onResponse(List<Comment> response);
void onError(String errorMessage);
}
公共接口CommentsServiceResultListener{
无效响应(列表响应);
void onError(字符串错误消息);
}
首先,您需要实现getCommonsService接口,以便实际获取数据。你可以这样做:
public class GetCommensServiceImpl implemens GetCommensService {
private static final String TAG = BuildingsBaseServiceImpl.class.getSimpleName();
@Override
public void getComments(int id, CommentsServiceResultListener listener) {
CommentsService service = getService();
Call<List<Comment>> request = service.getCommentsOfPost(id);
request.enqueue(new Callback<List<Comment>>(){
@Override //if this method is executed, the actual call has been made
public void onResponse(Call<List<Comment>> call, Response<List<Comment>> response) {
if (response.isSuccessful()) {
listener.onResponse(response.body());
} else {
//TODO check here if the call wans't successful because a network problem. In that case, fetch from your SQLite
//Default unsuccessful call management
Log.e(TAG, response.code() + ": " + response.message());
listener.onError(response.message());
}
}
@Override //maybe the call couldn't be made because of lack of connection.
public void onFailure(Call<List<Comment>> call, Throwable t) {
//TODO check the failure cause, then decide if there's need to fetch from your SQLite.
//Default failure management
Log.e(TAG, t.getMessage() + "", t);
listener.onError(t.getMessage() + "");
}
});
}
private CommentsService getService() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://your.base.url/")
.addConverterFactory(GsonConverterFactory.create()) //assuming JSON
.build();
return retrofit.create(CommentsService.class);
}
}
公共类GetCommonsService实现GetCommonsService{
私有静态最终字符串标记=BuildingsBaseServiceImpl.class.getSimpleName();
@凌驾
public void getComments(int-id,CommentsServiceResultListener侦听器){
CommentsService=getService();
调用请求=service.getCommentsOfPost(id);
request.enqueue(新回调(){
@Override//如果执行此方法,则实际调用已完成
public void onResponse(调用调用,响应响应){
if(response.issusccessful()){
onResponse(response.body());
}否则{
//TODO在此检查是否由于网络问题而导致WAN调用失败。在这种情况下,请从SQLite获取
//默认不成功呼叫管理
Log.e(标记,response.code()+”:“+response.message());
listener.onError(response.message());
}
}
@Override//可能由于缺少连接而无法进行呼叫。
失败时公共无效(调用调用,可丢弃的t){
//TODO检查失败原因,然后决定是否需要从SQLite获取。
//默认故障管理
Log.e(标记,t.getMessage()+“”,t);
listener.onError(t.getMessage()+);
}
});
}
私有评论服务getService(){
改装改装=新改装.Builder()
.baseUrl(“http://your.base.url/")
.addConverterFactory(GsonConverterFactory.create())//假设为JSON
.build();
返回改装.create(CommentsService.class);
}
}
希望这有帮助 好吧,让我们设想一下,改造还提供了一种机制(例如,如果从DB加载错误,则通过传递特殊回调)。这将非常具体,因为:
- 如果我想更新令牌,用于安全数据
- 如果我想手动重新检查连接
- 如果我想显示特殊数据
public interface CommentsServiceListener {
void onResponse(List<Comment> response);
void onError(String errorMessage);
void onDataBaseLoadIfError(String errorMessage);
}
公共接口CommentsServiceListener{
无效响应(列表响应);
void onError(字符串错误消息);
void onDataBaseLoadIfError(字符串错误消息);
}
在我的一个项目中,我遇到了类似的问题,无法使用RxJava。我通过使用命令模式解决了这个问题
首先,我创建了一个带有清晰API的自定义回调类。这样我可以更简洁地处理HTTP代码(例如400或500)
这样,您将实现命令界面并使用它,而不是直接使用改装对象。例如,您可以创建一个
public interface CommentsServiceListener {
void onResponse(List<Comment> response);
void onError(String errorMessage);
void onDataBaseLoadIfError(String errorMessage);
}
public abstract class RestCallback<T> implements Callback<T> {
@Override
public void onResponse(Response<T> response, Retrofit retrofit) {
if (response != null) {
if (response.isSuccess()) {
onSuccess(response, retrofit);
} else {
onError(response, retrofit);
}
} else {
onFailure(null);
}
}
abstract public void onSuccess(Response<T> response, Retrofit retrofit);
abstract public void onError(Response<T> response, Retrofit retrofit);
abstract public void onFailure(Throwable t);
}
public interface Command {
// New network hit
void fresh(RestCallback callback);
// First cached if available then fresh
void all(RestCallback callback);
// Cached response only
void cached(RestCallback callback);
// If cache exists return it, otherwise return a fresh response
void get(RestCallback callback);
// Cancel the request
void cancel();
}