catalogue

  • 01. Network request exception classification
  • 02. Pay attention to problems in development
  • 03. Original treatment
  • 04. How can I reduce code coupling
  • 05. Unified handling procedure for exceptions
  • 06. Finished version code display

Good news

  • Summary of blog notes [March 2016 to present], including Java basic and in-depth knowledge points, Android technology blog, Python learning notes, etc., including the summary of bugs encountered in daily development, of course, I also collected a lot of interview questions in my spare time, updated, maintained and corrected for a long time, and continued to improve… Open source files are in Markdown format! At the same time, ALSO open source life blog, from 12 years, accumulated a total of N [nearly 1 million words, gradually moved to the Internet], reprint please indicate the source, thank you!
  • Link address:Github.com/yangchong21…
  • If you feel good, you can star, thank you! Of course, also welcome to put forward suggestions, everything starts from small, quantitative change causes qualitative change!

01. Network request exception classification

  • What are the network request exceptions?
    • One: Access interface exceptions, such as 404,500 exceptions, which Retrofit automatically throws.
    • Second: parsing data exceptions, data body changes may cause this problem.
    • Third: other types of exceptions, such as server response timeout exception, abnormal link failure, abnormal network connection and so on.
    • Fourth: Network request is successful, but the server defines the abnormal state, such as failure, token parameter error, or unified to prompt (man the place, such as shopping app, you buy n items requested interface successful, code is 200, but the server found that do not have so many goods, this time will give you a hint, Then the client takes this and toasts it.)

02. Pay attention to problems in development

  • During the process of retrieving the data, errors may occur when accessing the interface and parsing the data, and we can intercept errors at these two layers with interceptors.
    • 1. When accessing the interface, we don’t have to set up interceptors because Retrofit automatically throws exceptions when errors occur. For example, common request exceptions are 404,500,503 and so on. To facilitate troubleshooting, you can print logs in the DEBUG environment.
    • 2. When parsing data, we set an interceptor to determine whether the code in Result is successful. If not, we will throw the corresponding exception according to the error code agreed with the server. For example, the login page is switched after the token expires, the same account is disabled to log in to multiple devices, parameters are missing, and parameter transfer is abnormal.
    • 3. In addition, in order to avoid judging and processing errors in the View layer, we must also set an interceptor to intercept onError events and use ExceptionUtils to handle them separately according to the error type.

03. Original treatment

  • The simplest way to handle the throwable is to directly determine the type of the throwable returned
    / / request, To judge ServiceHelper throwable. GetInstance () getModelResult (param1, param2) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<Model>() { @Override public voidonCompleted() {
                  
                  }
    
                  @Override
                  public void onError(Throwable e) {
                      if(e instanceof HttpException){// Get the corresponding statusCode and Message HttpException exception = (HttpException)e; String message = exception.response().message(); int code = exception.response().code(); }else if(e instanceof SSLHandshakeException){// }else if(e instanceof ...){
    
                      }...
    			  }
    
                  @Override
                  public void onNext(Model model) {
                      if(model.getCode ! = CODE_SUCCESS){ int code = model.getCode(); switch (code){case CODE_TOKEN_INVALID:
                                    ex.setDisplayMessage("Re-landing");
                                    break;
                                case CODE_NO_OTHER:
                                    ex.setDisplayMessage("Other circumstances");
                                    break;
                                case CODE_SHOW_TOAST:
                                    ex.setDisplayMessage("Prompt returned from the toast server");
                                    break;
                                case CODE_NO_MISSING_PARAMETER:
                                    ex.setDisplayMessage("Missing parameter, log server prompt");
                                    break;
                                default:
                                    ex.setDisplayMessage(message);
                                    break; }}else{// Normal processing logic}}});Copy the code

04. How can I reduce code coupling

  • How can you completely decouple your code without changing the previous code structure? Typically using the Retrofit Network request framework, there are callback methods like this:
    package retrofit2;
    
    public interface Callback<T> {
        void onResponse(Call<T> var1, Response<T> var2);
    
        void onFailure(Call<T> var1, Throwable var2);
    }
    Copy the code
  • Regardless of the previous code encapsulation or not, it is hoped that a single code can realize the network request interception processing logic. So at this point, what did I do?
    public class ResponseData<T> {
    
        private int code;
        private String message;
        private T t;
    
        public int getCode() {
            return code;
        }
    
        public String getMessage() {
            return message;
        }
    
        public T getT() {
            return t;
        }
    }
    
    new Callback<ResponseData<HomeBlogEntity>>(){
        @Override
        public void onResponse(Call<ResponseData<HomeBlogEntity>> call,
                               Response<ResponseData<HomeBlogEntity>> response) {
            int code = response.body().getCode();
            String message = response.body().getMessage();
            HomeBlogEntity t = response.body().getT();
            if(code! = CODE_SUCCESS) {/ / network request success in 200, but the business layer to perform the service side of exception logic ExceptionUtils. ServiceException (code, message); }else{// Network request successful, }} @override public void onFailure(Call Call, Throwable throwable) { ExceptionUtils.handleException(throwable); }};Copy the code

05. Unified handling procedure for exceptions

  • Step 1: Define the status code of the request interface network layer failure
    Private static final int BAD_REQUEST = 400; private static final int BAD_REQUEST = 400; private static final int UNAUTHORIZED = 401; private static final int FORBIDDEN = 403; private static final int NOT_FOUND = 404; private static final int METHOD_NOT_ALLOWED = 405; private static final int REQUEST_TIMEOUT = 408; private static final int CONFLICT = 409; private static final int PRECONDITION_FAILED = 412; private static final int INTERNAL_SERVER_ERROR = 500; private static final int BAD_GATEWAY = 502; private static final int SERVICE_UNAVAILABLE = 503; private static final int GATEWAY_TIMEOUT = 504;Copy the code
  • Step 2, the interface request succeeds, the business layer fails, and the server defines the exception status code
    • For example, if the login expires, the user is reminded to log in again.
    • For example, add goods, but the server finds that the inventory is insufficient, this time the interface request succeeds, the server fails to define the business layer, the server gives a prompt, the client does the toast
    • For example, if the request interface or parameter is abnormal or the type is wrong, the request code is 200, but the prompt is given. At this time, the client uses log to print the prompt given by the server, which is convenient for the Courier to find the problem
    • For example, in other cases, the interface request succeeds, but the server defines the corresponding prompt that the business layer requires the toast server to return
    /** * Is the state defined by the server * for example: login expired, remind the user to log in again; * Add goods, but the server found inventory is insufficient, this time the interface request success, the server to define the business layer failed, the server gives a prompt, the client to toast * request interface, parameter exception or type error, request code is 200 success status, but give a prompt, this time the client uselogPrivate static final int CODE_SUCCESS = 0; private static final int CODE_SUCCESS = 0;  /** * Token invalid */ public static final int CODE_TOKEN_INVALID = 401; Public static final int CODE_NO_MISSING_PARAMETER = 400400; Public static final int CODE_NO_OTHER = 403; Public static final int CODE_SHOW_TOAST = 400000;Copy the code
  • Third, customize Http layer exceptions and server-defined exception classes
    public class HttpException extends Exception {
    
        private int code;
        private String displayMessage;
    
        public HttpException(Throwable throwable, int code) {
            super(throwable);
            this.code = code;
        }
    
        public void setDisplayMessage(String displayMessage) {
            this.displayMessage = displayMessage;
        }
    
        public String getDisplayMessage() {
            return displayMessage;
        }
    
        public int getCode() {
            return code;
        }
    }
    
    public class ServerException extends RuntimeException {
    
        public int code;
        public String message;
    
        public int getCode() {
            return code;
        }
    
        public void setCode(int code) {
            this.code = code;
        }
    
        @Override
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) { this.message = message; }}Copy the code
  • The fourth step, the unified exception handling logic is as follows
    /** * This can handle server request success, but business logic failure, * @param code User-defined code */ public static void serviceException(int code, String content){if(code ! = CODE_SUCCESS){ ServerException serverException = new ServerException(); serverException.setCode(code); serverException.setMessage(content); handleException(serverException); Public static void handleException(Throwable e){HttpException ex;}} public static void handleException(Throwable e){HttpException ex; //HTTP error network request exception such as common 404 500 etcif (e instanceof retrofit2.HttpException){
            retrofit2.HttpException httpException = (retrofit2.HttpException) e;
            ex = new HttpException(e, ErrorCode.HTTP_ERROR);
            switch(httpException.code()){
                case BAD_REQUEST:
                case UNAUTHORIZED:
                case FORBIDDEN:
                case NOT_FOUND:
                case METHOD_NOT_ALLOWED:
                case REQUEST_TIMEOUT:
                case CONFLICT:
                case PRECONDITION_FAILED:
                case GATEWAY_TIMEOUT:
                case INTERNAL_SERVER_ERROR:
                case BAD_GATEWAY:
                caseSERVICE_UNAVAILABLE: // Both are regarded as network errors default: ex.setDisplayMessage("Network error"+httpException.code());
                    break; }}else if(e instanceof ServerException){// Error returned by the server ServerException resultException = (ServerException) e; int code = resultException.getCode(); String message = resultException.getMessage(); ex = new HttpException(resultException, ErrorCode.SERVER_ERROR); switch (code){case CODE_TOKEN_INVALID:
                    ex.setDisplayMessage("Token failure"); // The login page can be redirected to the login pagebreak;
                case CODE_NO_OTHER:
                    ex.setDisplayMessage("Other circumstances");
                    break;
                case CODE_SHOW_TOAST:
                    ex.setDisplayMessage("Toast");
                    break;
                case CODE_NO_MISSING_PARAMETER:
                    ex.setDisplayMessage("Missing parameters");
                    break;
                default:
                    ex.setDisplayMessage(message);
                    break; }}else if(e instanceof JsonParseException || e instanceof JSONException || e instanceof ParseException){ ex = new HttpException(e, ErrorCode.PARSE_ERROR); Ex.setdisplaymessage (ex.setDisplayMessage)"Parsing error");
        }else if(e instanceof ConnectException){ ex = new HttpException(e, ErrorCode.NETWORK_ERROR); // All treated as network error ex.setDisplayMessage("Connection failed");
        } else if(e instanceof java.net.UnknownHostException){ ex = new HttpException(e, ErrorCode.NETWORK_ERROR); // The network is not connected ex.setDisplayMessage("Network is not connected");
        } else if(e instanceof SocketTimeoutException) { ex = new HttpException(e, ErrorCode.NETWORK_ERROR); // The network is not connected ex.setDisplayMessage("Server response timed out");
        }  else{ ex = new HttpException(e, ErrorCode.UNKNOWN); // Unknown error ex.setDisplayMessage("Unknown error"); } String displayMessage = ex.getDisplayMessage(); / / here toast logging abnormal content directly, pay attention to the formal project must pay attention to toast the right contents ToastUtils. ShowRoundRectToast (displayMessage); }Copy the code
  • Step 5, how to call
    @ Override public void onError (Throwable e) {/ / can be called directly ExceptionUtils handleException (e); }Copy the code

06. Finished version code display

  • As shown below.
    Public Class ExceptionUtils {/* * When using Retrofit+RxJava, we access the interface and get the data by following the usual process: Subscribe -> Access the interface -> parse the data -> display. * As mentioned above, exceptions and errors are essentially the same, so we should try to avoid judging and handling errors in the View layer. * * During the process of retrieving data, errors may occur when accessing the interface and parsing the data. Interceptors can intercept errors at these two layers. * 1. We don't have to set up interceptors when accessing the interface, because Retrofit automatically throws an exception when an error occurs. * 2. When parsing data, we set an interceptor to determine whether the code in Result is successful. If not, we will throw the corresponding exception according to the error code agreed with the server. * 3. In addition, in order to avoid the judgment and processing of errors in the View layer, we must also set an interceptor to intercept onError events, and then use ExceptionHandler to handle them separately according to the error type. */ private static final int BAD_REQUEST = 400; private static final int UNAUTHORIZED = 401; private static final int FORBIDDEN = 403; private static final int NOT_FOUND = 404; private static final int METHOD_NOT_ALLOWED = 405; private static final int REQUEST_TIMEOUT = 408; private static final int CONFLICT = 409; private static final int PRECONDITION_FAILED = 412; private static final int INTERNAL_SERVER_ERROR = 500; private static final int BAD_GATEWAY = 502; private static final int SERVICE_UNAVAILABLE = 503; private static final int GATEWAY_TIMEOUT = 504; /** * Is the state defined by the server * for example: login expired, remind the user to log in again; * Add goods, but the server found inventory is insufficient, this time the interface request success, the server to define the business layer failed, the server gives a prompt, the client to toast * request interface, parameter exception or type error, request code is 200 success status, but give a prompt, this time the client uselogPrivate static final int CODE_SUCCESS = 0; private static final int CODE_SUCCESS = 0;  /** * Token invalid */ public static final int CODE_TOKEN_INVALID = 401; Public static final int CODE_NO_MISSING_PARAMETER = 400400; Public static final int CODE_NO_OTHER = 403; Public static final int CODE_SHOW_TOAST = 400000; /** * This can handle server request success, but business logic failure, * @param code User-defined code */ public static void serviceException(int code, String content){if(code ! = CODE_SUCCESS){ ServerException serverException = new ServerException(); serverException.setCode(code); serverException.setMessage(content); handleException(serverException); Public static void handleException(Throwable e){HttpException ex;}} public static void handleException(Throwable e){HttpException ex; //HTTP error network request exception such as common 404 500 etcif (e instanceof retrofit2.HttpException){
                retrofit2.HttpException httpException = (retrofit2.HttpException) e;
                ex = new HttpException(e, ErrorCode.HTTP_ERROR);
                switch(httpException.code()){
                    case BAD_REQUEST:
                    case UNAUTHORIZED:
                    case FORBIDDEN:
                    case NOT_FOUND:
                    case METHOD_NOT_ALLOWED:
                    case REQUEST_TIMEOUT:
                    case CONFLICT:
                    case PRECONDITION_FAILED:
                    case GATEWAY_TIMEOUT:
                    case INTERNAL_SERVER_ERROR:
                    case BAD_GATEWAY:
                    caseSERVICE_UNAVAILABLE: // Both are regarded as network errors default: ex.setDisplayMessage("Network error"+httpException.code());
                        break; }}else if(e instanceof ServerException){// Error returned by the server ServerException resultException = (ServerException) e; int code = resultException.getCode(); String message = resultException.getMessage(); ex = new HttpException(resultException, ErrorCode.SERVER_ERROR); switch (code){case CODE_TOKEN_INVALID:
                        ex.setDisplayMessage("Re-landing");
                        break;
                    case CODE_NO_OTHER:
                        ex.setDisplayMessage("Other circumstances");
                        break;
                    case CODE_SHOW_TOAST:
                        ex.setDisplayMessage("Toast");
                        break;
                    case CODE_NO_MISSING_PARAMETER:
                        ex.setDisplayMessage("Missing parameters");
                        break;
                    default:
                        ex.setDisplayMessage(message);
                        break; }}else if(e instanceof JsonParseException || e instanceof JSONException || e instanceof ParseException){ ex = new HttpException(e, ErrorCode.PARSE_ERROR); Ex.setdisplaymessage (ex.setDisplayMessage)"Parsing error");
            }else if(e instanceof ConnectException){ ex = new HttpException(e, ErrorCode.NETWORK_ERROR); // All treated as network error ex.setDisplayMessage("Connection failed");
            } else if(e instanceof java.net.UnknownHostException){ ex = new HttpException(e, ErrorCode.NETWORK_ERROR); // The network is not connected ex.setDisplayMessage("Network is not connected");
            } else if(e instanceof SocketTimeoutException) { ex = new HttpException(e, ErrorCode.NETWORK_ERROR); // The network is not connected ex.setDisplayMessage("Server response timed out");
            }  else{ ex = new HttpException(e, ErrorCode.UNKNOWN); // Unknown error ex.setDisplayMessage("Unknown error"); } String displayMessage = ex.getDisplayMessage(); / / here toast logging abnormal content directly, pay attention to the formal project must pay attention to toast the right contents ToastUtils. ShowRoundRectToast (displayMessage); }}Copy the code

The other is introduced

01. About blog summary links

  • 1. Tech blog round-up
  • 2. Open source project summary
  • 3. Life Blog Summary
  • 4. Himalayan audio summary
  • 5. Other summaries

02. About my blog

  • Github:github.com/yangchong21…
  • Zhihu: www.zhihu.com/people/yczb…
  • Jane: www.jianshu.com/u/b7b2c6ed9…
  • csdn:my.csdn.net/m0_37700275
  • The Himalayan listening: www.ximalaya.com/zhubo/71989…
  • Source: China my.oschina.net/zbj1618/blo…
  • Soak in the days of online: www.jcodecraeer.com/member/cont.
  • Email address: [email protected]
  • Blog: ali cloud yq.aliyun.com/users/artic… 239.headeruserinfo.3.dT4bcV
  • Segmentfault headline: segmentfault.com/u/xiangjian…
  • The Denver nuggets: juejin. Cn/user / 197877…

Open source code cases:Github.com/yangchong21…