XUtils3--代码详解(一)

作者: carrey001 | 来源:发表于2016-06-13 18:19 被阅读2115次

    XUtil3详解二---http

    官方readme.me

    • xUtils 包含了很多实用的android工具.
    • xUtils 支持超大文件(超过2G)上传,更全面的http请求协议支持(11种谓词),拥有更加灵活的ORM,更多的事件注解支持且不受混淆影响...
    • xUtils 最低兼容Android 4.0 (api level 14). (Android 2.3?)
    • xUtils3变化较多所以建立了新的项目不在旧版(github.com/wyouflf/xUtils)上继续维护, 相对于旧版本:
      -- HTTP实现替换HttpClient为UrlConnection, 自动解析回调泛型, 更安全的断点续传策略.-- 支持标准的Cookie策略, 区分domain, path...
      -- 事件注解去除不常用的功能, 提高性能.-- 数据库api简化提高性能, 达到和greenDao一致的性能.
      -- 图片绑定支持gif, webp; 支持圆角, 圆形, 方形等裁剪, 支持自动旋转...需要权限:
    <uses-permissionandroid:name="android.permission.INTERNET" />
    <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    

    初始化:

    // 在application的onCreate中初始化
    @Override
    public void onCreate() {
       super.onCreate();
       x.Ext.init(this);
       x.Ext.setDebug(true); // 是否输出debug日志...
    }
    

    访问网络

    /** * 自定义实体参数类请参考:
    * 请求注解 {@link org.xutils.http.annotation.HttpRequest} 
    * 请求注解处理模板接口 {@link org.xutils.http.app.ParamsBuilder} 
    * * 需要自定义类型作为callback的泛型时, 参考:
    * 响应注解 {@link org.xutils.http.annotation.HttpResponse}
    * 响应注解处理模板接口 {@link org.xutils.http.app.ResponseParser} 
    * * 示例: 查看 org.xutils.sample.http 包里的代码 
    */
    BaiduParams params =newBaiduParams();params.wd ="xUtils";// 有上传文件时使用multipart表单, 否则上传原始文件流.
    // params.setMultipart(true);
    // 上传文件方式 1
    // params.uploadFile = new File("/sdcard/test.txt");// 上传文件方式 2// params.addBodyParameter("uploadFile", new File("/sdcard/test.txt"));Callback.Cancelable cancelable = x.http().get(params,
    /** * 1. callback的泛型: 
    * callback参数默认支持的泛型类型参见{@link org.xutils.http.loader.LoaderFactory}, 
    * 例如: 指定泛型为File则可实现文件下载, 使用params.setSaveFilePath(path)指定文件保存的全路径. 
    * 默认支持断点续传(采用了文件锁和尾端校验续传文件的一致性). 
    * 其他常用类型可以自己在LoaderFactory中注册, 
    * 也可以使用{@link org.xutils.http.annotation.HttpResponse} 
    * 将注解HttpResponse加到自定义返回值类型上, 实现自定义ResponseParser接口来统一转换. 
    * 如果返回值是json形式, 那么利用第三方的json工具将十分容易定义自己的ResponseParser. 
    * 如示例代码{@link org.xutils.sample.http.BaiduResponse}, 可直接使用BaiduResponse作为 
    * callback的泛型. 
    * * 2. callback的组合: 
    * 可以用基类或接口组合个种类的Callback, 见{@link org.xutils.common.Callback}. 
    * 例如: 
    * a. 组合使用CacheCallback将使请求检测缓存或将结果存入缓存(仅GET请求生效). 
    * b. 组合使用PrepareCallback的prepare方法将为callback提供一次后台执行耗时任务的机会, * 然后将结果给onCache或onSuccess. 
    * c. 组合使用ProgressCallback将提供进度回调. 
    * ...(可参考{@link org.xutils.image.ImageLoader} 
    * 或 示例代码中的 {@link org.xutils.sample.download.DownloadCallback}) * * 3. 请求过程拦截或记录日志: 参考 {@link org.xutils.http.app.RequestTracker} 
    * * 4. 请求Header获取: 参考 {@link org.xutils.http.app.RequestInterceptListener} 
    * * 5. 其他(线程池, 超时, 重定向, 重试, 代理等): 参考 {@link org.xutils.http.RequestParams} 
    * **/
    newCallback.CommonCallback<String>() { 
      @Override
      public void onSuccess(Stringresult) { 
        Toast.makeText(x.app(), result, Toast.LENGTH_LONG).show();
       } 
      @Override
      public void onError(Throwableex, booleanisOnCallback) { 
        //Toast.makeText(x.app(), ex.getMessage(),Toast.LENGTH_LONG).show();
        if (ex instanceofHttpException) { // 网络错误HttpException
           httpEx = (HttpException) ex;
           int responseCode = httpEx.getCode();
           String responseMsg = httpEx.getMessage();
           String errorResult = httpEx.getResult();
          // ... 
        } else {
           // 其他错误
          //   ... 
      } 
      Toast.makeText(x.app(), ex.getMessage(), Toast.LENGTH_LONG).show();
    } 
      @Override
      public void onCancelled(CancelledExceptioncex) {
         Toast.makeText(x.app(), "cancelled", Toast.LENGTH_LONG).show(); 
      } 
      @Override 
      public void onFinished() { } }); 
    // cancelable.cancel();  
    // 取消请求
    

    简单版本

    RequestParams params =newRequestParams("https://www.baidu.com/s"); 
    
    params.setSslSocketFactory(...); // 设置ssl 
    params.addQueryStringParameter("wd", "xUtils"); 
    x.http().get(params, newCallback.CommonCallback<String>() { 
      @Override
      public void onSuccess(Stringresult) {
         Toast.makeText(x.app(), result, Toast.LENGTH_LONG).show(); 
      } 
      @Override
      public void onError(Throwableex, booleanisOnCallback) { 
          Toast.makeText(x.app(), ex.getMessage(), T  oast.LENGTH_LONG).show(); 
      } 
      @Override
      public void onCancelled(CancelledExceptioncex) {  
          Toast.makeText(x.app(), "cancelled", Toast.LENGTH_LONG).show(); 
      }
       @Override
      public void onFinished() { } });
    
    

    带有缓存的请求示例:

    BaiduParams params =newBaiduParams();
    params.wd ="xUtils";// 默认缓存存活时间, 单位:毫秒.(如果服务没有返回有效的max-age或Expires)params.setCacheMaxAge(1000*60);
    Callback.Cancelable cancelable // 使用CacheCallback, xUtils将为该请求缓存数据.
          = x.http().get(params, newCallback.CacheCallback<String>() { 
          private boolean hasError =false; 
          privateString result =null; 
          @Override
          public boolean onCache(Stringresult) { // 得到缓存数据, 缓存过期后不会进入这个方法.
          // 如果服务端没有返回过期时间, 参考params.setCacheMaxAge(maxAge)方法.//
          // * 客户端会根据服务端返回的 header 中 max-age 或 expires 来确定本地缓存是否给 onCache 方法.
          // 如果服务端没有返回 max-age 或 expires, 那么缓存将一直保存, 除非这里自己定义了返回false的// 逻辑, 那么xUtils将请求新数据, 来覆盖它.//
          // * 如果信任该缓存返回 true, 将不再请求网络;
          // 返回 false 继续请求网络, 但会在请求头中加上ETag, Last-Modified等信息,
          // 如果服务端返回304, 则表示数据没有更新, 不继续加载数据.
          //this.result = result; return false; 
          // true: 信任缓存数据, 不在发起网络请求; false不信任缓存数据. 
          } 
          @Override
          public void onSuccess(Stringresult) { // 注意: 如果服务返回304或 onCache 选择了信任缓存, 这里将不会被调用,
          // 但是 onFinished 总会被调用.
          this.result = result; 
          }
         @Override
          public void onError(Throwableex, booleanisOnCallback) { 
              hasError =true;
             Toast.makeText(x.app(), ex.getMessage(),   Toast.LENGTH_LONG).show(); 
    
            if (ex instanceofHttpException) { 
            // 网络错误
            HttpException httpEx = (HttpException) ex;
            int responseCode = httpEx.getCode(); 
            String responseMsg = httpEx.getMessage();
             String errorResult = httpEx.getResult(); 
              // ... 
            } else { 
            // 其他错误// ... 
            }
           } 
            @Override
          public void onCancelled(CancelledExceptioncex) { 
            Toast.makeText(x.app(), "cancelled", Toast.LENGTH_LONG).show();
          }
           @Override
          public void onFinished() { 
            if (!hasError && result !=null) { // 成功获取数据
            Toast.makeText(x.app(), result, Toast.LENGTH_LONG).show();
             }
           }
        });
    

    绑定图片

    
    x.image().bind(imageView, url, imageOptions);
    
    // assets file
    x.image().bind(imageView, "assets://test.gif", imageOptions);
    
    // local file
    x.image().bind(imageView, newFile("/sdcard/test.gif").toURI().toString(), imageOptions);
    x.image().bind(imageView, "/sdcard/test.gif", imageOptions);
    x.image().bind(imageView, "file:///sdcard/test.gif", imageOptions);
    x.image().bind(imageView, "file:/sdcard/test.gif", imageOptions);
    x.image().bind(imageView, url, imageOptions, newCallback.CommonCallback<Drawable>() {...});
    x.image().loadDrawable(url, imageOptions, newCallback.CommonCallback<Drawable>() {...});
    x.image().loadFile(url, imageOptions, newCallback.CommonCallback<File>() {...});
    
    

    查看源码:


    主要类x.class

    这个类为任务控制中心, http, image, db, view注入等接口的入口. 需要在在application的onCreate中初始化: x.Ext.init(this);

    作者把所有的入口全放到x.class 类中。内部静态类 Ext来管理和创建几个manager对象(httpManager ImageManager 等 全为接口)我查了词典。Ext 翻译过来有 提取 扩展 外部的意思。

    ** * Created by wyouflf on 15/6/10. 
    * 任务控制中心, http, image, db, view注入等接口的入口. 
    * 需要在在application的onCreate中初始化: x.Ext.init(this); 
    */
    public final class x {
     ...
    public static TaskController task() {
          return Ext.taskController;
    }
    public static HttpManager http() {...}
    public static ImageManager image() {...}
    public static ViewInjector view(){...}
    public static DbManager getDb(DbManager.DaoConfig daoConfig){...}
    public static class Ext {
    private static boolean debug; 
    private static Application app; 
    private static TaskController taskController;
    private static HttpManager httpManager;
    private static ImageManager imageManager; 
    private static ViewInjector viewInjector;
    private Ext() { }
      static { 
    TaskControllerImpl.registerInstance();
    // 默认信任所有https域名
    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
    @Override
    public boolean verify(String hostname, SSLSession session) {return true;} 
    });
    }
    public static void init(Application app) {
          if (Ext.app == null) {
              Ext.app = app;
          }
    } 
    ... }
    private static class MockApplication extends Application {
    public MockApplication(Context baseContext) {
          this.attachBaseContext(baseContext);
          }
        }
    }
    
    
    

    在x.class中 ,除去几个应用的方法。我发现了TaskController 这个对象。从字面上理解应该是task控制类。我们发现TaskController 是一个接口。并且和他的实现类在common包下面,所有task相关的应该xutils3中通用的一个模块或者实现方式

    common包下面的一些类和接口
    查看TaskController和TaskControllerImpl发现 这是task管理的一个控制类。
    **TaskController.class **
    /** * 
    Created by wyouflf on 15/6/11. 
    * 任务管理接口
    */
    public interface TaskController {
    /** 
    * 在UI线程执行runnable. 
    * 如果已在UI线程, 则直接执行. 
    * * @param runnable
    */
    void autoPost(Runnable runnable);
    /** 
    * 在UI线程执行runnable. 
    * post到msg queue. 
    * * @param runnable
    */
    void post(Runnable runnable);
    /** 
    * 在UI线程执行runnable. 
    * * @param runnable
    * @param delayMillis 延迟时间(单位毫秒) 
    */
    void postDelayed(Runnable runnable, long delayMillis);
    /** 
    * 在后台线程执行runnable 
    * * @param runnable
    */
    void run(Runnable runnable);
    /** 
    * 移除未执行的runnable 
    * * @param runnable
    */
    void removeCallbacks(Runnable runnable);
    /** 
    * 开始一个异步任务
    * * @param task
    * @param <T>
    * @return*/
    <T> AbsTask<T> start(AbsTask<T> task);
    /** * 同步执行一个任务
    * * @param task
    * @param <T>
    * @return
    * @throws Throwable 
    */
    <T> T startSync(AbsTask<T> task) throws Throwable;
    /** 
    * 批量执行异步任务
    * * @param groupCallback
    * @param tasks* @param <T>
    * @return
    */
    <T extends AbsTask<?>> Callback.Cancelable startTasks(Callback.GroupCallback<T> groupCallback, T... tasks);
    }
    
    

    TaskControllerImpl.class 在实现类中我们发现。它的作用应该是1.回调函数发回主线程。2.目标task的dobackground方法执行

    
    @Override
    public void autoPost(Runnable runnable) {
    if (runnable == null) return; 
    if (Thread.currentThread() == Looper.getMainLooper().getThread()) { 
        runnable.run();
    } else { 
    TaskProxy.sHandler.post(runnable);
    }
    }
    /** 
    * run task 
    * * @param task
    * @param <T>
    * @return
    */
    @Override
    public <T> AbsTask<T> start(AbsTask<T> task) { 
    TaskProxy<T> proxy = null;
     if (task instanceof TaskProxy) {
          proxy = (TaskProxy<T>) task;
    } else { 
          proxy = new TaskProxy<T>(task);
    }
    try {
     proxy.doBackground();
    } catch (Throwable ex) {
    LogUtil.e(ex.getMessage(), ex);
    }
    return proxy;
    }
    
    @SuppressWarnings("unchecked")
    @Override 
        public <T extends AbsTask<?>> Callback.Cancelable startTasks( final Callback.GroupCallback<T> groupCallback, final T... tasks) {
           if (tasks == null) { 
              throw new IllegalArgumentException("task must not be null"); 
            } 
            final Runnable callIfOnAllFinished = new Runnable() { 
              private final int total = tasks.length; 
              private final AtomicInteger count = new AtomicInteger(0);
             @Override 
             public void run() {
               if (count.incrementAndGet() == total) {
                 if (groupCallback != null) {
                 groupCallback.onAllFinished();
                 }
               }
             }
         }; 
    
         for (final T task : tasks) {
               start(new TaskProxy(task) {
                 @Override 
                  protected void onSuccess(Object result) { 
                    super.onSuccess(result);
                     post(new Runnable() {
                       @Override 
                        public void run() { 
                        if (groupCallback != null) {
                         groupCallback.onSuccess(task); 
                         }
                       }
                      }); 
                    } 
                @Override
                 protected void onCancelled(final Callback.CancelledException cex) { 
                          super.onCancelled(cex);
                          post(new Runnable() { 
                              @Override
                              public void run() {
                                    if (groupCallback != null) {
                                           groupCallback.onCancelled(task, cex);
                                     }
                               }
                           }); 
                      } 
                 @Override 
                  protected void onError(final Throwable ex, final boolean isCallbackError) { 
                        super.onError(ex, isCallbackError);
                        post(new Runnable() {
                             @Override
                             public void run() {
                             if (groupCallback != null) {
                             groupCallback.onError(task, ex, isCallbackError); 
                              } 
                          } 
                        });
                   } 
                 @Override
                 protected void onFinished() {
                 super.onFinished(); 
                 post(new Runnable() { 
                      @Override 
                      public void run() {
                             if (groupCallback != null) { 
                                    groupCallback.onFinished(task);
                             } 
                            callIfOnAllFinished.run(); 
                      } 
                  });
           } 
        });
     } 
    return new Callback.Cancelable() { 
          @Override
           public void cancel() {
                for (T task : tasks) {
                    task.cancel(); 
                } 
          } 
          @Override 
          public boolean isCancelled() { 
              boolean isCancelled = true;
               for (T task : tasks) { 
                    if (!task.isCancelled()){ 
                    isCancelled = false; 
                    } 
                }
             return isCancelled;
         } 
        }; 
    }
    

    Task相关

    在TaskControllerImpl中出现了俩个类AysTask.class 和TaskProxy.class

    • AysTask 异步任务基类
      AysTask是异步任务的基类并且是个抽象类。实现了callback的取消接口 继承AysTask 必须要复写三个方法doBackground,onSuccess,onError
    /** 
    * Created by wyouflf on 15/6/5. 
    * 异步任务基类 
    * * @param <ResultType> 
    */
    public abstract class AbsTask<ResultType> implements Callback.Cancelable {
     private TaskProxy taskProxy = null;
     private final Callback.Cancelable cancelHandler;
     private volatile boolean isCancelled = false;
     private volatile State state = State.IDLE;
     private ResultType result;
      ... 
     protected abstract ResultType doBackground() throws Throwable;
     protected abstract void onSuccess(ResultType result);
     protected abstract void onError(Throwable ex, boolean isCallbackError);
     ...
     @Override
    //通用的异步加载的cancel方法
     public final synchronized void cancel() {
     if (!this.isCancelled) {
     this.isCancelled = true;
     cancelWorks();
     if (cancelHandler != null && !cancelHandler.isCancelled()) { 
        cancelHandler.cancel(); 
      }
     if (this.state == State.WAITING || (this.state == State.STARTED && isCancelFast())) {
       if (taskProxy != null) {
       taskProxy.onCancelled(new Callback.CancelledException("cancelled by user"));
       taskProxy.onFinished();
       } else if (this instanceof TaskProxy) {
        this.onCancelled(new Callback.CancelledException("cancelled by user")); 
        this.onFinished();
         }
      } 
     } 
     }
     @Override
     public final boolean isCancelled() {
     return isCancelled || state == State.CANCELLED || (cancelHandler != null && cancelHandler.isCancelled());
     }
     public enum State {//线程的几个状态 大学里应该学过
     IDLE(0), WAITING(1), STARTED(2), SUCCESS(3), CANCELLED(4), ERROR(5);
     private final int value;
     private State(int value) { this.value = value; }
     public int value() { return value; } }}
    

    注释:
    volatile:就像大家更熟悉的const一样,volatile是一个类型修饰符(type specifier)。它是被设计用来修饰被不同线程访问和修改的变量。如果不加入volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器失去大量优化的机会。(ps:写这篇博客之前根本不知道这个东西)

    • TaskProxy
      Taskproxy 异步任务的代理类。这里面有两个重要的成员变量handle 和PriorityExecutor 。
      在代码
      private InternalHandler() {
      super(Looper.getMainLooper());
      }
      看到 handle 是依靠MainThread 创建的。
      所有最后发送出去的message都会被 Mainthread接受。PriorityExecutor 为线程池。
      这里不多讲了。
    
    /** * 异步任务的代理类(仅在task包内可用) 
    * * @param <ResultType> 
    */
    /*package*/ class TaskProxy<ResultType> extends AbsTask<ResultType> { 
    /*package*/ static final InternalHandler sHandler = new InternalHandler(); 
    /*package*/ static final PriorityExecutor sDefaultExecutor = new PriorityExecutor(true);
     private final AbsTask<ResultType> task;
     private final Executor executor;
     private volatile boolean callOnCanceled = false;
     private volatile boolean callOnFinished = false;
     /*package*/ TaskProxy(AbsTask<ResultType> task) {
             super(task);
             this.task = task;  
             this.task.setTaskProxy(this);
             this.setTaskProxy(null);
             Executor taskExecutor = task.getExecutor();
             if (taskExecutor == null) {
                 taskExecutor = sDefaultExecutor;
             }
             this.executor = taskExecutor;
         }
         @Override 
          protected final ResultType doBackground() throws Throwable {
               this.onWaiting();
               PriorityRunnable runnable = new PriorityRunnable(
               task.getPriority(),
               new Runnable() {
                 @Override public void run() {
                   try { // 等待过程中取消 
                        if (callOnCanceled || TaskProxy.this.isCancelled()) {
                                  throw new Callback.CancelledException("");
                         }
                   // start running 
                  TaskProxy.this.onStarted();
                 if (TaskProxy.this.isCancelled()) {
                 // 开始时取消 
                    throw new Callback.CancelledException(""); 
                  }
               // 执行task, 得到结果.
               task.setResult(task.doBackground()); 
              TaskProxy.this.setResult(task.getResult()); 
              // 未在doBackground过程中取消成功
             if (TaskProxy.this.isCancelled()) { 
                    throw new Callback.CancelledException("");
               }
               // 执行成功 
            TaskProxy.this.onSuccess(task.getResult());
           } catch (Callback.CancelledException cex) {
                 TaskProxy.this.onCancelled(cex);
           } catch (Throwable ex) {
                 TaskProxy.this.onError(ex, false);
           } finally {
                 TaskProxy.this.onFinished();
           }
       }
     });
     this.executor.execute(runnable);
     return null;
     }
     @Override
     protected void onSuccess(ResultType result) {
         this.setState(State.SUCCESS);
           sHandler.obtainMessage(MSG_WHAT_ON_SUCCESS, this).sendToTarget();
         }
     @Override
     /*package*/ final void setState(State state) { super.setState(state); this.task.setState(state); }
     // ########################### inner type #############################
     private static class ArgsObj {
         final TaskProxy taskProxy;
     final Object[] args;
     public ArgsObj(TaskProxy taskProxy, Object... args) {
         this.taskProxy = taskProxy;
         this.args = args;
       }
     }
     private final static int MSG_WHAT_BASE = 1000000000;
     private final static int MSG_WHAT_ON_WAITING = MSG_WHAT_BASE + 1;
     private final static int MSG_WHAT_ON_START = MSG_WHAT_BASE + 2; private final static int MSG_WHAT_ON_SUCCESS = MSG_WHAT_BASE + 3;
     private final static int MSG_WHAT_ON_ERROR = MSG_WHAT_BASE + 4; 
    private final static int MSG_WHAT_ON_UPDATE = MSG_WHAT_BASE + 5; 
    private final static int MSG_WHAT_ON_CANCEL = MSG_WHAT_BASE + 6;
     private final static int MSG_WHAT_ON_FINISHED = MSG_WHAT_BASE + 7;
     /*package*/ final static class InternalHandler extends Handler {
     private InternalHandler() { super(Looper.getMainLooper()); } 
    @Override 
    @SuppressWarnings("unchecked")
     public void handleMessage(Message msg) {
     if (msg.obj == null) {
     throw new IllegalArgumentException("msg must not be null"); 
    } .......  
    }}
    
    
    

    现在主要看 handle的处理方法handleMessage:
    在方法中
    会得到一个TaskProxy代理对象.
    TaskProxy.task为构建对象时候传递进来的一个AbsTask实现类。
    该实现类里面会实现一些 成功或失败的方法。 然后 handle会通过what来区别和调用onSuccess ,onError

    @Override 
    @SuppressWarnings("unchecked")
     public void handleMessage(Message msg) {
     if (msg.obj == null) {
     throw new IllegalArgumentException("msg must not be null");
     } 
    TaskProxy taskProxy = null;
     Object[] args = null; 
    if (msg.obj instanceof TaskProxy) { 
    taskProxy = (TaskProxy) msg.obj;
     } else if (msg.obj instanceof ArgsObj) { 
    ArgsObj argsObj = (ArgsObj) msg.obj;
     taskProxy = argsObj.taskProxy; 
    args = argsObj.args;
     } if (taskProxy == null) { 
    throw new RuntimeException("msg.obj not instanceof TaskProxy"); 
    }
     try {
     switch (msg.what) {
     case MSG_WHAT_ON_WAITING: {
     taskProxy.task.onWaiting();
     break; 
    } 
    case MSG_WHAT_ON_START: {
     taskProxy.task.onStarted();
     break; 
    } 
    case MSG_WHAT_ON_SUCCESS: { 
    taskProxy.task.onSuccess(taskProxy.getResult());
     break;
     } 
    case MSG_WHAT_ON_ERROR: { 
    assert args != null;
     Throwable throwable = (Throwable) args[0]; 
    LogUtil.d(throwable.getMessage(), throwable); 
    taskProxy.task.onError(throwable, false);
     break;
     } 
    case MSG_WHAT_ON_UPDATE: {
     taskProxy.task.onUpdate(msg.arg1, args);
     break; 
    }
     case MSG_WHAT_ON_CANCEL: {
     if (taskProxy.callOnCanceled) return; 
    taskProxy.callOnCanceled = true; 
    assert args != null; 
    taskProxy.task.onCancelled((org.xutils.common.Callback.CancelledException) args[0]); break;
     } 
    case MSG_WHAT_ON_FINISHED: {
     if (taskProxy.callOnFinished) return;
     taskProxy.callOnFinished = true;
     taskProxy.task.onFinished();
     break; 
    } 
    default: {
     break; 
    } 
    } 
    } catch (Throwable ex) { 
    taskProxy.setState(State.ERROR);
    
     if (msg.what != MSG_WHAT_ON_ERROR) { 
    taskProxy.task.onError(ex, true); 
    } else if (x.isDebug()) { 
    throw new RuntimeException(ex);
     }
     } }
    

    xutils3.Http待续

    相关文章

      网友评论

      • 850018ed5563:你好,我想请问一下,xutils的event点击,为什么我将手机系统时间修改为当前时间之前,然后点击事件就不触发了?请问是什么原因?谢谢

      本文标题:XUtils3--代码详解(一)

      本文链接:https://www.haomeiwen.com/subject/khvydttx.html