2016-06-27 25 views
6

Tôi muốn biết cách xử lý các loại lỗi khác nhau (như ngoại lệ http, không có ngoại lệ kết nối internet, v.v.) trong retrofit Rx onError mà không sử dụng instanceof được đề xuất ở đây: How to handle network errors in Retrofit 2 with RxJava hoặc tại đây: Handle errors in Retrofit 2 RXLàm thế nào để xử lý các loại lỗi khác nhau trong Retrofit Rx onError mà không xấu xí instanceof

Trong kotlin Tôi sẽ chỉ cần thực hiện một số chức năng mở rộng cho từng loại có thể ném được để làm bất kỳ điều gì tôi muốn.

Nhưng tôi buộc phải sử dụng Java trong dự án. Bất kỳ đề xuất tốt đẹp?

là cách tiếp cận để xây dựng một số loại xử lý lỗi như thế này:

public interface ErrorHandler { 
    void handleError(Exception e); 
    void handleError(HttpException e); 
    void handleError(NullPointerException npe); 

} 

tốt? Tôi biết nó không phải là bởi vì mỗi khi tôi cần phải xử lý một lỗi cụ thể khác, tôi buộc phải thay đổi giao diện, do đó, nó là vi phạm nguyên tắc đóng mở. Nhưng tôi không thể tìm ra giải pháp nào.

cổ vũ Wojtek

+0

điều này sẽ luôn nằm trong 'handleError (ngoại lệ e)' thực hiện – mihail

+0

hmmm, tôi đã viết kiểm tra cho nó và nó không thất bại ... nhưng nó không liên quan: P –

+0

Tôi cũng đã viết một thử nghiệm trong Java 1.8 (u60) và nó rơi luôn trong phương pháp Exception – mihail

Trả lời

1

Trình biên dịch sẽ xác định phương pháp để gọi, chứ không phải là VM. Vì vậy, các lớp học bạn đã mô tả sẽ không giải quyết được vấn đề, trừ khi bạn kiểm tra instanceof đầu tiên và cast paramter cho đúng loại. Nếu không, bạn sẽ nhận được handleError (Ngoại lệ e) mỗi lần.

Nhưng tôi muốn tạo câu trả lời không vì lý do đó, nhưng để cho rằng chỉ có một trình xử lý lỗi thực sự thích hợp hơn trong nhiều trường hợp, không phải là trách nhiệm pháp lý. Thông thường trong java, chúng tôi kết thúc trong các tình huống khủng khiếp như thế này:

catch (NoSuchAlgorithmException e) { 
     throw new IllegalStateException("No such algorithm: RSA?", e); 
    } 
    catch (NoSuchProviderException e) { 
     throw new IllegalStateException("No such provider: " + ANDROID_KEYSTORE_ID, e); 
    } 
    catch (InvalidAlgorithmParameterException e) { 
     throw new IllegalStateException("Bug setting up encryption key for user credentials: ", e); 
    } 
    catch (KeyStoreException e) { 
     throw new IllegalStateException("Bug setting up encryption key for user credentials: ", e); 
    } 
    catch (IOException e) { 
     Log.w(TAG, "Exception setting up keystore for user creds. They won't be stored.", e); 
    } 
    catch (CertificateException e) { 
     Log.w(TAG, "Exception setting up keystore for user creds. They won't be stored.", e); 
    } 

Chỉ có một trình xử lý lỗi cho phép chúng tôi gộp nhiều loại ngoại lệ lại với nhau. Bạn có thể thấy trong đoạn mã này, có những trường hợp ngoại lệ không bao giờ được ném, ngoại lệ có thể thực sự chỉ là kết quả của một lỗi trong mã, và các trạng thái ngoại lệ hợp pháp mà chúng ta cần xử lý. Tôi thấy lộn xộn này, và muốn nói:

if (e instanceof NoSuchAlgorithmException || e instanceof NoSuchProviderException) { 
    Log.wtf(TAG, "What the heck is this?", e); 
    throw new IllegalStateException("This is some kind of weird bug", e); 
} 
else if (e instanceof IOException || e instanceof CertificateException) { 
    // This can happen sometimes, track event in analytics and perhaps 
    // try some alternative means of credential storage. 
} 
else { 
    // At least here the app won't crash if some unexpected exception occurs, 
    // since we're trapping everything. 
} 

Tôi không nghĩ rằng đó là một điều xấu như vậy để có thể gộp những thất bại bất ngờ với nhau và xử lý chúng một cách thân thiện hơn đâm ứng dụng. Ngay cả khi nó chỉ là một lỗi, tốt hơn để theo dõi nó trong khuôn khổ phân tích của bạn đằng sau hậu trường hơn là ném bom người dùng ra khỏi ứng dụng. Vì vậy, nhiều sự cố trong ứng dụng Android thực sự có thể khôi phục hoàn toàn, nhưng chúng tôi không đi xung quanh việc bắt được Throwable trong mọi câu lệnh try/catch vì nó có nhiều mã bổ sung.

1

Cách OOP thích hợp để tránh bị xích if s hoặc catch es là đa hình. Bạn có thể định nghĩa một số lớp ngoại lệ tùy chỉnh để lộ giao diện chung đủ cho một trình xử lý đơn lẻ xử lý.

Giả sử bạn cần chia các lỗi trong hai nhóm: có thể khôi phục và không thể khôi phục được. Sau đó, lớp ngoại lệ cơ sở của bạn (hoặc giao diện) sẽ có phương thức trừu tượng isRecoverable() mà bạn ghi đè trong mỗi lớp con. Sau đó, sẽ chỉ có một if trong trình xử lý của bạn: if (e.isRecoverable()) { ... } else { ... }.

Nhược điểm là bạn phải bọc tất cả các ngoại lệ tiêu chuẩn vào các tùy chỉnh của bạn ở những nơi mà chúng được ném (bạn phải bắt chúng).

Sự lựa chọn đúng sẽ phụ thuộc rất nhiều vào nhiệm vụ của bạn.

Các vấn đề liên quan