2016-07-07 23 views
7

我已經通過thisthis發帖。所以我真的同意第二篇文章,主持人不應該意識到Android的具體事情。所以我在想的是將服務層的互聯網檢查。 我正在使用Rx Java進行網絡調用,因此我可以在進行服務調用之前進行網絡檢查,所以這樣我需要手動拋出和IOException,因爲當網絡不可用時需要在視圖上顯示錯誤頁面,另一種選擇是創建自己的錯誤類沒有互聯網互聯網支票,使用MVP,RX和改造時的地點

Observable<PaginationResponse<Notification>> response = Observable.create(new Observable.OnSubscribe<PaginationResponse<Notification>>() { 
      @Override 
      public void call(Subscriber<? super PaginationResponse<Notification>> subscriber) { 
       if (isNetworkConnected()) { 
        Call<List<Notification>> call = mService.getNotifications(); 
        try { 
         Response<List<Notification>> response = call.execute(); 
         processPaginationResponse(subscriber, response); 
        } catch (IOException e) { 
         e.printStackTrace(); 
         subscriber.onError(e); 
        } 
       } else { 
//This is I am adding manually 
        subscriber.onError(new IOException); 
       } 
       subscriber.onCompleted(); 
      } 
     }); 

雖然我是加入攔截OkHttpClient的另一種方式,並設置爲改造

OkHttpClient.Builder builder = new OkHttpClient().newBuilder(); 
     builder.addInterceptor(new Interceptor() { 
      @Override 
      public Response intercept(Chain chain) throws IOException { 
       if (!isNetworkConnected()) { 
        throw new IOException(); 
       } 
       final Request.Builder builder = chain.request().newBuilder(); 

       Request request = builder.build(); 

       return chain.proceed(request); 
      } 
     }); 

現在第二個方法更可擴展的,但我不確定它會有效,因爲我會不必要地調用服務方法和call.execute( ) 方法。

任何建議應該使用哪種方式? 也是我的判斷方法的參數是

  • 效率

  • 可擴展性

  • 通用:我想這同樣的邏輯可以跨越誰遵循了類似的架構,MVP和存儲庫的應用程序中使用/ DataProvider(可提供來自網絡/ db的數據)

其他建議也歡迎,如果你的人已經在使用任何其他方式。

回答

9

首先,我們創建用於檢查網絡連接的工具,有兩種方法,我們可以創建此工具,一個地方公用事業發射狀態只有一次,它看起來像這樣,

public class InternetConnection { 
    public static Observable<Boolean> isInternetOn(Context context) { 
     ConnectivityManager connectivityManager 
       = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 
     NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo(); 
     return Observable.just(activeNetworkInfo != null && activeNetworkInfo.isConnected()); 
    } 
} 

的其他方式創建這個工具,在工具保持發光的連接狀態,如果它的變化,它看起來像這樣,

public class InternetConnection { 
    public Observable<Boolean> isInternetOn(Context context) { 
     final IntentFilter filter = new IntentFilter(); 
     filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 

     return Observable.create(new Observable.OnSubscribe<Boolean>() { 
      @Override 
      public void call(final Subscriber<? super Boolean> subscriber) { 
       final BroadcastReceiver receiver = new BroadcastReceiver() { 
        @Override 
        public void onReceive(Context context, Intent intent) { 
         ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 
         NetworkInfo netInfo = cm.getActiveNetworkInfo(); 
         subscriber.onNext(netInfo != null && netInfo.isConnected()); 
        } 
       }; 

       context.registerReceiver(receiver, filter); 

       subscriber.add(unsubscribeInUiThread(() -> context.unregisterReceiver(receiver))); 
      } 
     }).defaultIfEmpty(false); 
    } 

    private Subscription unsubscribeInUiThread(final Action0 unsubscribe) { 
     return Subscriptions.create(() -> { 
      if (Looper.getMainLooper() == Looper.myLooper()) { 
       unsubscribe.call(); 
      } else { 
       final Scheduler.Worker inner = AndroidSchedulers.mainThread().createWorker(); 
       inner.schedule(() -> { 
        unsubscribe.call(); 
        inner.unsubscribe(); 
       }); 
      } 
     }); 
    } 
} 

接下來,在你的數據源或演示使用switchMap或flatMap檢查互聯網連接前做任何看起來像這樣的網絡操作,

private Observable<List<GitHubUser>> getGitHubUsersFromRetrofit() { 
    return isInternetOn(context) 
      .filter(connectionStatus -> connectionStatus) 
      .switchMap(connectionStatus -> gitHubApiInterface.getGitHubUsersList() 
        .map(gitHubUserList -> { 
         gitHubUserDao.storeOrUpdateGitHubUserList(gitHubUserList); 
         return gitHubUserList; 
        })); 
} 

請注意,我們使用switchMap而不是flatMap。爲什麼使用switchMap?因爲我們在這裏有兩個數據流,第一個是互聯網連接,第二個是改造。首先我們將獲取連接狀態值(true/false),如果我們有活動連接,我們將創建一個新的Retrofit流並返回開始獲取結果,如果連接狀態發生變化,那麼switchMap會首先停止現有的改造連接,然後決定是否需要啓動一個新的或忽略它。

編輯: 這是樣品的一種,這可能會提供更好的清晰度https://github.com/viraj49/Realm_android-injection-rx-test/blob/master/app-safeIntegration/src/main/java/tank/viraj/realm/dataSource/GitHubUserListDataSource.java

EDIT2:

所以你的意思切換地圖會嘗試自己曾經的互聯網又回來了?

是的,我們先看看flatMap & switchMap的區別。假設我們有一個editText,並且我們根據用戶類型搜索網絡中的一些信息,每當用戶添加一個新字符時,我們必須創建一個新的查詢(可以通過去抖動來減少),現在只有很多網絡調用最新的結果是有用的,與flatMap我們將收到我們對網絡所做的所有電話的所有結果,另一方面,switchMap,當我們進行查詢時,所有先前的呼叫都被丟棄。

現在,這裏的溶液是由2份,

  1. 我們需要一個可觀察,保持發光網絡的當前狀態下,第一InternetConnection上述發送狀態一次,並調用的onComplete(),但是第二一個有廣播接收器,當網絡狀態改變時它將繼續發送onNext()。如果您需要製作一個反應式解決方案,請轉至案例2

  2. 假設您選擇InternetConnection案例2,在這種情況下使用switchMap(),導致網絡狀態更改時,我們需要停止Retrofit然後根據網絡的狀態做出新的呼叫或不打電話。

如何讓我的看法知道錯誤是互聯網一個也將在可伸縮性,因爲我需要與每一個網絡電話的事,關於寫作的包裝有什麼建議?

編寫包裝將是一個很好的選擇,您可以創建自己的自定義響應,可以從一組可能的響應中獲取多個條目,例如, SUCCESS_INTERNET,SUCCESS_LOGIN,ERROR_INVALID_ID

EDIT3:請點擊這裏https://github.com/viraj49/Realm_android-injection-rx-test/blob/master/app-safeIntegration/src/main/java/tank/viraj/realm/util/InternetConnection.java

更多細節上的同一主題找到更新的InternetConnectionUtil是在這裏:https://medium.com/@Viraj.Tank/android-mvp-that-survives-view-life-cycle-configuration-internet-changes-part-2-6b1e2b5c5294

EDIT4:我最近創建了採用Android架構組件的互聯網工具 - LiveData,你可以在這裏找到完整的源代碼, https://github.com/viraj49/Internet-Utitliy-using-AAC-LiveData

代碼的詳細描述在這裏, https://medium.com/@Viraj.Tank/internet-utility-using-android-architecture-components-livedata-e828a0fcd3db

+0

不錯!我非常感謝你的回答,但只有幾點。你能告訴我關於最後一行的更多信息,然後決定是否需要啓動一個新的或者忽略它,所以你的意思是一旦互聯網回來,轉換圖將自己嘗試它? 另外,我對一件事情並不感到滿意,我不打網絡電話,但還有兩件事情,我如何讓我的觀點知道錯誤是互聯網,這也是可擴展的,因爲我需要處理每個網絡電話,有關編寫包裝的任何建議? –

+0

用EDIT2標籤更新了響應 –

+0

明白了,你可以做一個更多的編輯並解釋InternetConnects類中的接收器註銷嗎?對不起,我的延遲響應。 –