RXJava,Retrofit,Android SocketTimeOutException当第二次搜索没有互联网时

时间:2018-06-01 14:49:21

标签: android retrofit2 rx-java2 youtube-data-api socket-timeout-exception

HY! 我使用YouTube Search API进行练习任务。 我想搜索视频,然后播放。所以我使用retrofit和rx进行服务通信。 我的问题是:

如果我在第一次搜索时没有互联网,请发送unkwon主机异常。 (没关系,因为我可以重试搜索,如果我有互联网连接获取新数据!)

如果我有互联网,我正在通过我的查询寻找第一个视频,它总是好的。当我从互联网断开连接并且我想要通过新查询或“旧”查询(+ pagetoken)的新视频时,总是抛出SocketTimeoutException。然后我再次使用互联网连接进行新查询抛出SocketTimeoutException。为什么? 有人有任何想法!?

我的YouTubeServiceImpl课程用于沟通:

YouTubeWebService youTubeWebService;

@Inject
public YouTubeServiceImpl(YouTubeWebService youTubeWebService) {
    this.youTubeWebService = youTubeWebService;
}

@Override
public Observable<VideoSearchResult> search(String query) {
    Map<String,String> queryMap = createBaseQueryMap(query);

    return createVideoSearchResult(VideoSearchResultCode.THERE_ARE_NO_VIDEOS_BY_QUERY,R.string.no_videos_found,queryMap);
}

@Override
public Observable<VideoSearchResult> search(String query, String pageToken) {
    Map<String,String> queryMap = createBaseQueryMap(query);
    queryMap.put(YOUTUBE_SEARCH_PAGE_TOKEN_KEY,pageToken);

    return createVideoSearchResult(VideoSearchResultCode.NO_MORE_PAGES,R.string.no_more_pages,queryMap);
}

private Observable<VideoSearchResult> createVideoSearchResult(final VideoSearchResultCode zeroItemsResultCode,
                                                              final int zeroItemMsgId,Map<String,String> queryMap){

    return youTubeWebService.search(queryMap).map(new Function<SearchResponse, VideoSearchResult>() {
        @Override
        public VideoSearchResult apply(SearchResponse response) {
            if (response.items.size() <= 0){
                return new VideoSearchResult(zeroItemsResultCode,zeroItemMsgId);
            }
            return new VideoSearchResult(createVideoItemList(response.items),response.nextPageToken);
        }
    }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}

private Map<String,String> createBaseQueryMap(String query){
    Map<String,String> queryMap = new HashMap<>();

    queryMap.put(YOUTUBE_SEARCH_PART_KEY,YOUTUBE_SEARCH_PART_SNIPPET_KEY);
    queryMap.put(YOUTUBE_SEARCH_KEY_KEY,YOUTUBE_SEARCH_API_KEY_VALUE);
    queryMap.put(YOUTUBE_SEARCH_TYPE_KEY,YOUTUBE_SEARCH_VIDEO_TYPE_KEY);
    queryMap.put(YOUTUBE_SEARCH_Q_KEY,query);
    queryMap.put(YOUTUBE_SEARCH_MAX_RESULTS_KEY,YOUTUBE_SEARCH_MAX_RESULTS_VALUE_KEY);

    return queryMap;
}

private List<VideoItem> createVideoItemList(List<SearchResponse.Item> items){
    List<VideoItem> videoItems = new ArrayList<>();

    for (SearchResponse.Item item : items) {
        ///TODO: Create item and add to list
        videoItems.add(new VideoItem(item.id.videoId,item.snippet.title,
                item.snippet.description,item.snippet.thumbnails.aDefault.url));
    }

    return videoItems;
}

YouTube网站服务由Dagger2提供:

 @Provides
@Singleton
static YouTubeWebService provideYouTubeWebService(){
    return createYouTubeRetrofit().create(YouTubeWebService.class);
}

private static Retrofit createYouTubeRetrofit(){
    return new Retrofit.Builder()
            .baseUrl(YOUTUBE_API_BASE_URL_KEY)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .client(createYouTubeOkHttpClient())
            .build();
}

private static OkHttpClient createYouTubeOkHttpClient(){
    return new OkHttpClient.Builder().addNetworkInterceptor(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();

            // try the request
            Response response = chain.proceed(request);

            int tryCount = 0;
            while (!response.isSuccessful() && tryCount < 3) {

                Log.d("intercept", "Request is not successful - " + tryCount);
                tryCount++;

                // retry the request
                response = chain.proceed(request);
            }

            // otherwise just pass the original response on
            return response;
        }
    }).build();
}

VideoItemDataSource(用于分页库)中的基本服务用法

private static final String LOG_TAG = "VideoItemDataSource";
YouTubeService youTubeService;
String query;
String pageToken;

public VideoItemDataSource(YouTubeService youTubeService,String query) {
    this.youTubeService = youTubeService;
    this.query = query;
}

@Override
public void loadInitial(@NonNull LoadInitialParams<String> params, @NonNull LoadInitialCallback<VideoItem> callback) {
    youTubeService.search(query).subscribe(new DisposableObserver<VideoSearchResult>() {
        @Override
        public void onNext(VideoSearchResult result) {
            Log.d(LOG_TAG,"loadInitial onNext: " + result.toString());
            pageToken = result.getPageToken();
            callback.onResult(result.getVideoItemList());
        }

        @Override
        public void onError(Throwable e) {
            Log.d(LOG_TAG,"loadInitial onError: " + e.toString());
            e.printStackTrace();
        }

        @Override
        public void onComplete() {
            Log.d(LOG_TAG,"loadInitial onComplete: ");
        }
    });
}

@Override
public void loadAfter(@NonNull LoadParams<String> params, @NonNull LoadCallback<VideoItem> callback) {
    youTubeService.search(query,pageToken).subscribe(new DisposableObserver<VideoSearchResult>() {
        @Override
        public void onNext(VideoSearchResult result) {
            Log.d(LOG_TAG,"loadAfter onNext: " + result.toString());
            pageToken = result.getPageToken();
            callback.onResult(result.getVideoItemList());
        }

        @Override
        public void onError(Throwable e) {
            Log.d(LOG_TAG,"loadAfter onError: " + e.toString());
            e.printStackTrace();
        }

        @Override
        public void onComplete() {
            Log.d(LOG_TAG,"loadAfter onComplete: ");
        }
    });
}

@Override
public void loadBefore(@NonNull LoadParams<String> params, @NonNull LoadCallback<VideoItem> callback) {

}

@NonNull
@Override
public String getKey(@NonNull VideoItem item) {
    return item.getId();
}

所以我想要没有sockettimeoutexception的新搜索,如果我有互联网但以前的搜索没有互联网。 有没有人知道解决方案是什么? 重要!我的Android虚拟设备遇到此问题(API22,27) 但我的真实设备没有经验(小米Redmi 3 PRO API 22 [?])

0 个答案:

没有答案