Android app开发中Retrofit框架的初步上手使用

2019-12-10 19:05:41王振洲

 Callback请求中函数最后一个参数是一个Callback的实例,httpExecutor是一个Executor,用于执行Runnable请求,我们看到,这里new了一个CallbackRunnable执行,并实现了它的obtainResponse方法,看实现:

abstract class CallbackRunnable<T> implements Runnable {
 private final Callback<T> callback;
 private final Executor callbackExecutor;
 private final ErrorHandler errorHandler;

 CallbackRunnable(Callback<T> callback, Executor callbackExecutor, ErrorHandler errorHandler) {
  this.callback = callback;
  this.callbackExecutor = callbackExecutor;
  this.errorHandler = errorHandler;
 }

 @SuppressWarnings("unchecked")
 @Override public final void run() {
  try {
   final ResponseWrapper wrapper = obtainResponse();
   callbackExecutor.execute(new Runnable() {
    @Override public void run() {
     callback.success((T) wrapper.responseBody, wrapper.response);
    }
   });
  } catch (RetrofitError e) {
   Throwable cause = errorHandler.handleError(e);
   final RetrofitError handled = cause == e ? e : unexpectedError(e.getUrl(), cause);
   callbackExecutor.execute(new Runnable() {
    @Override public void run() {
     callback.failure(handled);
    }
   });
  }
 }

 public abstract ResponseWrapper obtainResponse();
} 

就是一个普通的Runnable,在run方法中首先执行obtailResponse,从名字可以看到是执行请求返回Response,这个从前面可以看到执行了invokeRequest,和同步调用中一样执行请求。
紧接着就提交了一个Runnable至callbackExecutor,在看Platform时看到了callbackExecotor是通过Platform.get().defaultCallbackExecutor()返回的,Android中是向主线程的一个Handler发消息

值得注意的事,对于同步调用,如果遇到错误是直接抛异常,而对于异步调用,是调用Callback.failure()

Mime

执行网络请求,需要向服务端发送请求参数,如表单数据,上传的文件等,同样需要解析服务端返回的数据,在Retrofit中对这些做了封装,位于Mime包中,也只有封装了,才好统一由指定的Converter执行数据的转换

TypedInput和TypedOutput表示输入输出的数据,都包含mimeType,并分别支持读入一个InputStream或写到一个OutputStrem

/**
 * Binary data with an associated mime type.
 *
 * @author Jake Wharton (jw@squareup.com)
 */
public interface TypedInput {

 /** Returns the mime type. */
 String mimeType();

 /** Length in bytes. Returns {@code -1} if length is unknown. */
 long length();

 /**
  * Read bytes as stream. Unless otherwise specified, this method may only be called once. It is
  * the responsibility of the caller to close the stream.
  */
 InputStream in() throws IOException;
}

/**
 * Binary data with an associated mime type.
 *
 * @author Bob Lee (bob@squareup.com)
 */
public interface TypedOutput {
 /** Original filename.
  *
  * Used only for multipart requests, may be null. */
 String fileName();

 /** Returns the mime type. */
 String mimeType();

 /** Length in bytes or -1 if unknown. */
 long length();

 /** Writes these bytes to the given output stream. */
 void writeTo(OutputStream out) throws IOException;
}

TypedByteArray,内部数据是一个Byte数组

 private final byte[] bytes;

 @Override public long length() {
  return bytes.length;
 }

 @Override public void writeTo(OutputStream out) throws IOException {
  out.write(bytes);
 }

 @Override public InputStream in() throws IOException {
  return new ByteArrayInputStream(bytes);
 }

TypedString,继承自TypedByteArray,内部表示是一样的

public TypedString(String string) {
  super("text/plain; charset=UTF-8", convertToBytes(string));
 }

 private static byte[] convertToBytes(String string) {
  try {
   return string.getBytes("UTF-8");
  } catch (UnsupportedEncodingException e) {
   throw new RuntimeException(e);
  }
 }