zoukankan      html  css  js  c++  java
  • Okhttp 简介 示例 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱
    MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

    目录

    OkHttp

    okhttp
    官网
    文档
    API

    You'll also need Okio , which OkHttp uses for fast I/O and resizable调整 buffers。
    Okio的API文档

    compile 'com.squareup.okhttp3:okhttp:3.8.0'
    compile 'com.squareup.okio:okio:1.13.0'

    okhttp-3.9.0.jar
    okio-1.13.0.jar

    简介

    Android下的网络框架:

    • 官方集成的网络框架包含:HttpUrlConnection、HttpClient、Volley。
    • Volley是android开发团队在2013年Google I/O大会上推出了一个新的网络通信框架。目前Volley中部分代码仍然借助于HttpClient中部分功能,然而HttpClient在Android 6.0中已经被剔除掉了,如果想要使用Volley还必须使用一个第三方的jai包。
    • Volley是针对数据量不大,但通信频繁的网络操作,而对于大数据量的网络操作,比如说下载文件等,Volley的表现就会非常糟糕。
    • 如果使用HttpUrlConnection则要从头开始封装对应的操作。

    OkHttp是一个 Java 的 HTTP+SPDY 客户端开发包,同时也支持 Android,需要 Android 2.3 以上,同时还需要一个okio包。

    • OKHttp是Android(Java)版Http客户端,非常高效,支持SPDY、连接池、GZIP和 HTTP 缓存
    • 默认情况下,OKHttp会自动处理常见的网络问题,像二次连接、SSL的握手问题
    • 如果你的应用程序中集成了OKHttp,Retrofit默认会使用OKHttp处理其网络层请求
    • 从Android4.4开始,HttpURLConnection的底层实现采用的是okHttp

    PS:
    SPDY(读作“SPeeDY”)是Google开发的基于TCP的应用层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验。
    SPDY并不是一种用于替代HTTP的协议,而是对HTTP协议的增强。
    新协议的功能包括数据流的多路复用、请求优先级以及HTTP报头压缩。
    谷歌表示,引入SPDY协议后,在实验室测试中页面加载速度比原先快64%。

    官方 Overview

    HTTP is the way modern applications network. It's how we exchange data & media. Doing HTTP efficiently makes your stuff材料、塞满 load faster and saves bandwidth带宽.

    OkHttp is an HTTP client that's efficient by default:

    • HTTP/2 support allows all requests to the same host to share a socket.
    • Connection pooling连接池 reduces使变弱 request latency延迟 (if HTTP/2 isn't available).
    • Transparent GZIP透明的GZIP压缩 shrinks减少 download sizes.
    • Response caching avoids the network completely for repeat重复 requests.

    OkHttp perseveres坚忍 when the network is troublesome: it will silently沉默的 recover from common connection problems. If your service has multiple IP addresses, OkHttp will attempt alternate轮流、交替 addresses if the first connect fails. This is necessary for IPv4+IPv6 and for services hosted in redundant冗余的、多余的 data centers. OkHttp initiates开始 new connections with modern TLS features (SNI, ALPN), and falls back to TLS 1.0 if the handshake fails.

    Using OkHttp is easy. Its request/response API is designed with fluent流畅的 builders and immutability不变的. It supports both synchronous blocking calls and async calls with callbacks.

    OkHttp supports Android 2.3 and above. For Java, the minimum requirement is 1.7.

    Works with OkHttp

    Here’s some libraries that work nicely with OkHttp.

    • Glide: An image loading and caching library for Android focused on smooth scrolling. 专注于平滑滚动的Android图像加载和缓存库。
    • Okio: A modern I/O API for Java. Java的现代I/O API。
    • Retrofit: Type-safe HTTP client for Android and Java by Square. Square公司出的适用于Android和Java的类型安全的HTTP客户端。
    • Chuck: An in-app HTTP inspector for Android OkHttp clients. 适用于Android OkHttp客户端的应用内HTTP检查器。
    • Communicator: An OkHttp wrapper for Scala built with Android in mind. 安装了Android的Scala的OkHttp包装器。
    • CWAC-NetSecurity: Simplifying Secure Internet Access. 简化安全Internet访问。
    • Fresco: An Android library for managing images and the memory they use. 用于管理图像和他们使用的内存的Android库。
    • GoogleAppEngineOkHttp: An OkHttp Call that works on Google App Engine. 适用于Google App Engine的OkHttp调用。
    • ModernHttpClient: Xamarin HTTP API that uses native implementations. 使用本地实现的Xamarin HTTP API。
    • Moshi: A modern JSON library for Android and Java. Android和Java的现代JSON库。
    • Ok2Curl: Convert OkHttp requests into curl logs. 将OkHttp请求转换为curl日志。
    • okhttp-digest: A digest authenticator for OkHttp. OkHttp的摘要验证器。
    • OkHttp Idling Resource: An Espresso IdlingResource for OkHttp. OkHttp的浓咖啡空转资源。
    • okhttp-signpost: OAuth signing with signpost and OkHttp. OAuth签署路标和OkHttp。
    • okhttp-stats: Get stats like average network speed. 获取平均网络速度的统计信息。
    • OkHttp-Xamarin: Xamarin bindings for OkHttp. 用于OkHttp的Xamarin绑定。
    • OkLog: Response logging interceptor for OkHttp. Logs a URL link with URL-encoded response for every OkHttp call. OkHttp的响应记录拦截器。记录每个OkHttp调用的URL编码响应的URL链接。
    • OkSocial A curl-like client for social networks and other APIs. 社交网络和其他API的curl-like客户端。
    • PersistentCookieJar: A persistent CookieJar. 一个持久的CookieJar。
    • Picasso: A powerful image downloading and caching library for Android. 一个功能强大的Android图像下载和缓存库。
    • Smash: A Volley-inspired networking library. 一个受Volley启发的网络库。
    • Stetho: Stetho is a debug bridge for Android applications. Stetho是Android应用程序的调试桥。
    • Thrifty: An implementation of Apache Thrift for Android. 在Android上Apache Thrift的一个实现。
    • Volley-OkHttp-Android: A fork of Volley with changes to work with OkHttp. 使用OkHttp进行更改的fork自Volley的一个库。

    • Wire: Clean, lightweight protocol buffers for Android and Java. 适用于Android和Java的清洁、轻便的protocol buffers。

    示例代码

    get和post示例

    public class MainActivity extends ListActivity {
        private User mUser;
        private String mBaseUrl = "http://api.95xiu.com/";
        private OkHttpClient client;
    
        private TextView mTv;
    
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            String[] array = {"post方式提交键值对数据", "get方式提交键值对数据",};
            mTv = new TextView(this);
            getListView().addFooterView(mTv);
            setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, array));
    
            client=new OkHttpClient.Builder().build();
        }
    
        @Override
        protected void onListItemClick(ListView l, View v, int position, long id) {
            switch (position) {
                case 0:
                    postWithParams(); //post方式提交键值对数据
                    break;
                case 1:
                    getWithParams(); //get方式提交键值对数据
                    break;
            }
        }
    
        private void postWithParams() {
            String url = mBaseUrl + "user/loginv2.php";
            FormBody formBody = new FormBody.Builder()
                    .add("user", "103468")
                    .add("pass", "103468")
                    .build();
            Request request = new Request.Builder().url(url).post(formBody).build();
            client.newCall(request)
                    .enqueue(new okhttp3.Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                        }
    
                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            final String responseString = response.body().string();//响应的内容
                            Log.i("bqt", "【body】" + decodeUnicodeToString(responseString));//{"result":0,"msg":"用户不存在"}
    
                            mUser = new Gson().fromJson(responseString, User.class);//类型转换
                            runOnUiThread(() -> mTv.setText(decodeUnicodeToString(responseString)));//线程切换
                        }
                    });
        }
    
        private void getWithParams() {
            String url = mBaseUrl + "app/news/index.php"
                    + "?session_id=" + mUser.getMsg().getSession_id()
                    + "&uid=" + mUser.getMsg().getId();
            Request request = new Request.Builder().url(url).get().build();
            client.newCall(request)
                    .enqueue(new okhttp3.Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                        }
    
                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            final String responseString = response.body().string();
                            runOnUiThread(() -> mTv.setText(decodeUnicodeToString(responseString)));
                        }
                    });
        }
    
        //将Unicode编码解析成字符串形式(如汉字)
        public static String decodeUnicodeToString(String uString) {
            StringBuilder sb = new StringBuilder();
            int i = -1, pos = 0;
            while ((i = uString.indexOf("\u", pos)) != -1) {
                sb.append(uString.substring(pos, i));
                if (i + 5 < uString.length()) {
                    pos = i + 6;
                    sb.append((char) Integer.parseInt(uString.substring(i + 2, i + 6), 16));
                }
            }
            sb.append(uString.substring(pos));
            return sb.toString();
        }
    }

    拦截器和证书示例

    public class OkHttp_Activity extends ListActivity {
    
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            String[] array = {"应用程序拦截器",
                    "网络拦截器",
                    "Rewriting Requests,重写请求",
                    "Rewriting Responses,重写响应",};
            setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, array));
        }
    
        @Override
        protected void onListItemClick(ListView l, View v, int position, long id) {
            new Thread(() -> {//里面用的都是同步请求,所以必须在一个子线程中调用
                try {//线程里面的异常不能在线程外面捕获或throws
                    switch (position) {
                        case 0:
                            loggingInterceptor(true, new LoggingInterceptor());//应用程序拦截器
                            break;
                        case 1:
                            loggingInterceptor(false, new LoggingInterceptor());//网络拦截器
                            break;
                        case 2:
                            loggingInterceptor(new Random().nextBoolean(), new GzipRequestInterceptor());//重写请求
                            break;
                        case 3:
                            loggingInterceptor(new Random().nextBoolean(), new ReWriteCacheControlInterceptor());//重写响应
                            break;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    
        private void loggingInterceptor(boolean isApplicationInterceptor, Interceptor interceptor) throws IOException {
            OkHttpClient client;
            if (isApplicationInterceptor) client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
            else client = new OkHttpClient.Builder().addNetworkInterceptor(interceptor).build();
    
            Request request = new Request.Builder()
                    .url("http://publicobject.com/helloworld.txt")
                    .header("User-Agent", "OkHttp Example")
                    .build();
    
            Response response = client.newCall(request).execute(); //同步执行
            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
    
            System.out.println("【响应url】" + response.request().url());
            response.body().close();
        }
    
        //使用一个自定义的TLS版本和密码组来构建你自己的连接规范
        private void connectionSpecs() {
            ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
                    .tlsVersions(TlsVersion.TLS_1_2)
                    .cipherSuites(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
                            CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                            CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
                    .build();
    
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectionSpecs(Collections.singletonList(spec))
                    .build();
        }
    
        //Certificate Pinning,证书锁定
        public void certificatePinner() throws Exception {
            CertificatePinner certificatePinner = new CertificatePinner.Builder()
                    .add("publicobject.com", "sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=")
                    .build();
    
            OkHttpClient client = new OkHttpClient.Builder()
                    .certificatePinner(certificatePinner)
                    .build();
    
            Request request = new Request.Builder()
                    .url("https://publicobject.com/robots.txt")
                    .build();
    
            Response response = client.newCall(request).execute();
            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
    
            for (java.security.cert.Certificate certificate : response.handshake().peerCertificates()) {
                System.out.println("【】" + CertificatePinner.pin(certificate));
            }
        }
    
        //拦截器
        class LoggingInterceptor implements Interceptor {
            @Override
            public Response intercept(Interceptor.Chain chain) throws IOException {
                Request request = chain.request();//发出的请求
                long t1 = System.nanoTime();
                System.out.println("【请求】" + String.format("Sending request %s on %s%n%s",
                        request.url(), chain.connection(), request.headers()));
    
                Response response = chain.proceed(request);//生成与请求对应的响应。这里是所有HTTP工作发生的地方
                long t2 = System.nanoTime();
                System.out.println("【响应】" + String.format("Received response for %s in %.1fms%n%s",
                        response.request().url(), (t2 - t1) / 1e6d, response.headers()));
    
                return response;
            }
        }
    
        //This interceptor compresses the HTTP request body. Many webservers can't handle this!
        class GzipRequestInterceptor implements Interceptor {
            @Override
            public Response intercept(Interceptor.Chain chain) throws IOException {
                Request originalRequest = chain.request();
                if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
                    return chain.proceed(originalRequest);//生成与请求对应的响应
                }
    
                RequestBody compressedRequestBody = new RequestBody() {
                    @Override
                    public MediaType contentType() {
                        return originalRequest.body().contentType();
                    }
    
                    @Override
                    public long contentLength() {
                        return -1; // We don't know the compressed length in advance(提前)!
                    }
    
                    @Override
                    public void writeTo(BufferedSink sink) throws IOException {
                        BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
                        originalRequest.body().writeTo(gzipSink);
                        gzipSink.close();
                    }
                };
    
                Request compressedRequest = originalRequest.newBuilder()
                        .header("Content-Encoding", "gzip")//添加、删除或者替换请求头
                        .method(originalRequest.method(), compressedRequestBody)//改变请求体
                        .build();
                return chain.proceed(compressedRequest);//重新生成与请求对应的响应
            }
        }
    
        //Dangerous interceptor that rewrites the server's cache-control header.
        class ReWriteCacheControlInterceptor implements Interceptor {
            @Override
            public Response intercept(Interceptor.Chain chain) throws IOException {
                Response originalResponse = chain.proceed(chain.request());
                return originalResponse.newBuilder()
                        .header("Cache-Control", "max-age=60")//重写响应头
                        .build();
            }
        }
    }

    retrofit okhttp RxJava 综合示例

    依赖

    //【retrofit2】
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0'
    
    //【okhttp】
    compile 'com.squareup.okhttp3:okhttp:3.8.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'
    compile 'com.squareup.okio:okio:1.13.0'
    
    //【butterknife】
    compile 'com.jakewharton:butterknife:8.8.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
    
    //【rxjava】
    compile 'io.reactivex:rxandroid:1.1.0'
    compile 'io.reactivex:rxjava:1.1.6'

    网络请求接口定义

    public interface GitHubApi {
    
        @GET("repos/{owner}/{repo}/contributors")
        Call<ResponseBody> contributorsBySimpleGetCall(@Path("owner") String owner, @Path("repo") String repo);
    
        @GET("repos/{owner}/{repo}/contributors")
        Call<List<Contributor>> contributorsByAddConverterGetCall(@Path("owner") String owner, @Path("repo") String repo);
    
        @Headers({"Accept: application/vnd.github.v3.full+json", "User-Agent: RetrofitBean-Sample-App", "name:ljd"})
        @GET("repos/{owner}/{repo}/contributors")
        Call<List<Contributor>> contributorsAndAddHeader(@Path("owner") String owner, @Path("repo") String repo);
    
        @GET("search/repositories")
        Call<RetrofitBean> queryRetrofitByGetCall(@Query("q") String owner, @Query("since") String time, @Query("page") int page, @Query("per_page") int per_Page);
    
        @GET("search/repositories")
        Call<RetrofitBean> queryRetrofitByGetCallMap(@QueryMap Map<String, String> map);
    
        @GET("repos/{owner}/{repo}/contributors")
        Observable<List<Contributor>> contributorsByRxJava(@Path("owner") String owner, @Path("repo") String repo);
    
        @GET("users/{user}")
        Observable<User> userByRxJava(@Path("user") String user);
    
        @GET("/mobilesafe/shouji360/360safesis/360MobileSafe_6.2.3.1060.apk")
        Call<ResponseBody> retrofitDownload();
    }

    Activity

    public class MainActivity extends ListActivity {
        private TextView tv;
        private static final String baseUrl = "https://api.github.com/";
        private static final String mUserName = "square";//哪个公司【square】
        private static final String mRepo = "retrofit";//哪个项目【retrofit】
        private CompositeSubscription mSubscriptions = new CompositeSubscription();
    
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            String[] array = {"1、简单完整演示retrofit的使用",
                    "2、添加Gson转换器",
                    "3、添加okHttp的日志拦截器Interceptor",
                    "4、使用自己封装的API,演示@Headers",
                    "5、演示同步请求",
                    "6、演示@Query",
                    "7、演示@QueryMap",
                    "8、最简单、完整的retrofit+rxJava示例",
                    "9、rxJava+retrofit增强",
                    "10、演示文件下载",};
            tv = new TextView(this);
            tv.setTextColor(Color.BLUE);
            getListView().addFooterView(tv);
            setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, array));
        }
    
        @Override
        protected void onDestroy() {
            if (mSubscriptions != null) mSubscriptions.unsubscribe();
            super.onDestroy();
        }
    
        @Override
        protected void onListItemClick(ListView l, View v, int position, long id) {
            switch (position + 1) {
                case 1://简单完整演示retrofit的使用
                    requestGitHubContributorsSimple();
                    break;
                case 2://添加Gson转换器
                    requestGitHubContributorsByConverter();
                    break;
                case 3://添加okHttp的日志拦截器Interceptor
                    requestGitHubContributorsAddOkHttpLog();
                    break;
                case 4://使用自己封装的API,演示@Headers
                    requestGitHubContributorsAddHeader();
                    break;
                case 5://演示同步请求
                    requestGitHubContributorsBySync();
                    break;
                case 6://演示@Query
                    requestQueryRetrofitByGet(false);
                    break;
                case 7://演示@QueryMap
                    requestQueryRetrofitByGet(true);
                    break;
                case 8://最简单、完整的retrofit+rxJava示例
                    requestGitHubContributorsByRxJava();
                    break;
                case 9://rxJava+retrofit增强
                    requestGitHubContributorsWithFullUserInfo();
                    break;
                case 10://演示文件下载
                    retrofitDownload();
                    break;
            }
        }
    
        //1、简单示例
        private void requestGitHubContributorsSimple() {
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .build();
            GitHubApi repo = retrofit.create(GitHubApi.class);
            Call<ResponseBody> call = repo.contributorsBySimpleGetCall(mUserName, mRepo);
            call.enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
                    String result = null;
                    try {
                        result = response.body().string();
                        if (result == null) return;
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    tv.setText("GitHub上对项目的贡献-1:
    ");
                    ArrayList<Contributor> list = new Gson().fromJson(result, new TypeToken<List<Contributor>>() {
                            }.getType());
                    if (list == null || list.size() == 0) return;
                    for (Contributor contributor : list) {
                        tv.append(contributor.login + "    " + contributor.contributions + "
    ");
                    }
                }
    
                @Override
                public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
                    Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
                }
            });
        }
    
        //2、添加Gson转换器
        private void requestGitHubContributorsByConverter() {
            new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .addConverterFactory(GsonConverterFactory.create())//转换器
                    .build()
                    .create(GitHubApi.class)
                    .contributorsByAddConverterGetCall(mUserName, mRepo)
                    .enqueue(new Callback<List<Contributor>>() {
                        @Override
                        public void onResponse(@NonNull Call<List<Contributor>> call, @NonNull Response<List<Contributor>> response) {
                            List<Contributor> list = response.body();
                            tv.setText("GitHub上对项目的贡献-2:
    ");
                            if (list == null || list.size() == 0) return;
                            for (Contributor contributor : list) {
                                tv.append(contributor.login + "    " + contributor.contributions + "
    ");
                            }
                        }
    
                        @Override
                        public void onFailure(@NonNull Call<List<Contributor>> call, @NonNull Throwable t) {
                            Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
                        }
                    });
        }
    
        //3、添加okHttp的日志拦截器Interceptor
        private void requestGitHubContributorsAddOkHttpLog() {
            HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
    
            Retrofit retrofit = new Retrofit.Builder()
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .client(new OkHttpClient.Builder().addInterceptor(logInterceptor).build())
                    .baseUrl(baseUrl)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
    
            retrofit.create(GitHubApi.class)
                    .contributorsByAddConverterGetCall(mUserName, mRepo)
                    .enqueue(new Callback<List<Contributor>>() {
                        @Override
                        public void onResponse(@NonNull Call<List<Contributor>> call, @NonNull Response<List<com.bqt
                                .retrofit.bean.Contributor>> response) {
                            List<Contributor> list = response.body();
                            tv.setText("GitHub上对项目的贡献-3:
    ");
                            if (list == null || list.size() == 0) return;
                            for (Contributor contributor : list) {
                                tv.append(contributor.login + "    " + contributor.contributions + "
    ");
                            }
                        }
    
                        @Override
                        public void onFailure(@NonNull Call<List<Contributor>> call, @NonNull Throwable t) {
                            Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
                        }
                    });
        }
    
        //4、使用自己封装的API,演示@Headers
        private void requestGitHubContributorsAddHeader() {
            createRetrofitService(GitHubApi.class)
                    .contributorsAndAddHeader(mUserName, mRepo)
                    .enqueue(new Callback<List<Contributor>>() {
                        @Override
                        public void onResponse(@NonNull Call<List<Contributor>> call, @NonNull Response<List<com.bqt
                                .retrofit.bean.Contributor>> response) {
                            List<Contributor> list = response.body();
                            tv.setText("GitHub上对项目的贡献-4:
    ");
                            if (list == null || list.size() == 0) return;
                            for (Contributor contributor : list) {
                                tv.append(contributor.login + "    " + contributor.contributions + "
    ");
                            }
                        }
    
                        @Override
                        public void onFailure(@NonNull Call<List<Contributor>> call, @NonNull Throwable t) {
                        }
                    });
        }
    
        //5、演示同步请求
        private void requestGitHubContributorsBySync() {
            final Call<List<Contributor>> call = createRetrofitService(GitHubApi.class)
                    .contributorsByAddConverterGetCall(mUserName, mRepo);
            new Thread(() -> {
                try {
                    Response<List<Contributor>> response = call.execute();//在子线程中请求网络
                    final List<Contributor> list = response.body();
                    runOnUiThread(() -> {
                        tv.setText("GitHub上对项目的贡献-5:
    ");
                        for (Contributor contributor : list) {
                            tv.append(contributor.login + "    " + contributor.contributions + "
    ");
                        }
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    
        //6和7、演示@Query和@QueryMap
        private void requestQueryRetrofitByGet(boolean isQueryMap) {
            GitHubApi mGitHubService = createRetrofitService(GitHubApi.class);
            Call<RetrofitBean> call;
            if (!isQueryMap) call = mGitHubService.queryRetrofitByGetCall("retrofit", "2016-03-29", 1, 3);
            else {
                Map<String, String> queryMap = new HashMap<>();
                queryMap.put("q", "retrofit");
                queryMap.put("since", "2016-03-29");
                queryMap.put("page", "1");
                queryMap.put("per_page", "3");
                call = mGitHubService.queryRetrofitByGetCallMap(queryMap);
            }
    
            call.enqueue(new Callback<RetrofitBean>() {
                @Override
                public void onResponse(@NonNull Call<RetrofitBean> call, @NonNull Response<RetrofitBean> response) {
                    RetrofitBean retrofitBean = response.body();
                    if (retrofitBean == null) return;
                    List<Item> list = retrofitBean.getItems();
                    if (list == null || list.size() == 0) return;
    
                    tv.setText(new SimpleDateFormat("yyyy.MM.dd HH:mm:ss SSS", Locale.getDefault()).format(new Date()));
                    tv.append("
    total:" + retrofitBean.getTotalCount() + "
    incompleteResults:" + retrofitBean.getIncompleteResults());
                    for (Item item : list) {
                        tv.append("
    
    【name】" + item.name);
                        tv.append("
    【full_name】" + item.full_name);
                        tv.append("
    【 description】" + item.description);
                    }
                }
    
                @Override
                public void onFailure(@NonNull Call<RetrofitBean> call, @NonNull Throwable t) {
                }
            });
        }
    
        //8、最简单、完整的retrofit+rxJava示例
        private void requestGitHubContributorsByRxJava() {
            createRetrofitService(GitHubApi.class)
                .contributorsByRxJava(mUserName, mRepo)//
                .subscribeOn(Schedulers.io())//
                .observeOn(AndroidSchedulers.mainThread())//
                .subscribe(...);
        }
    
        //9、rxJava+retrofit增强
        private void requestGitHubContributorsWithFullUserInfo() {
            Subscription subscription = createRetrofitService(GitHubApi.class)
                .contributorsByRxJava(mUserName, mRepo)//
                .flatMap(...)
                .flatMap(...)
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(...;
            mSubscriptions.add(subscription);
        }
    
        //10、演示文件下载
        public void retrofitDownload() {
            //监听下载进度
            final ProgressDialog dialog = new ProgressDialog(this);
            dialog.setProgressNumberFormat("%1d KB/%2d KB");
            dialog.setTitle("下载");
            dialog.setMessage("正在下载,请稍后...");
            dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            dialog.setCancelable(false);
            dialog.show();
    
            ProgressHelper.setProgressHandler(new DownloadProgressHandler() {
                @Override
                protected void onProgress(long bytesRead, long contentLength, boolean done) {
                    //在主线程中运行
                    dialog.setMax((int) (contentLength / 1024));
                    dialog.setProgress((int) (bytesRead / 1024));
                    if (done) dialog.dismiss();
                }
            });
    
            Retrofit retrofit = new Retrofit.Builder()//
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//
                    .addConverterFactory(GsonConverterFactory.create())//
                    .baseUrl("http://msoftdl.360.cn")
                    .client(ProgressHelper.addProgress(null).build())
                    .build();
    
            retrofit.create(GitHubApi.class).retrofitDownload()
                    .enqueue(new Callback<ResponseBody>() {
                        @Override
                        public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
                            try {
                                InputStream is = response.body().byteStream();
                                File file = new File(Environment.getExternalStorageDirectory(), "12345.apk");
                                FileOutputStream fos = new FileOutputStream(file);
                                BufferedInputStream bis = new BufferedInputStream(is);
                                byte[] buffer = new byte[1024];
                                int len;
                                while ((len = bis.read(buffer)) != -1) {
                                    fos.write(buffer, 0, len);
                                    fos.flush();
                                }
                                fos.close();
                                bis.close();
                                is.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
    
                        @Override
                        public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
                        }
                    });
        }
    
        public static <T> T createRetrofitService(final Class<T> service) {
            HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor()
                .setLevel(HttpLoggingInterceptor.Level.BODY);
            OkHttpClient.Builder builder = new OkHttpClient.Builder().addInterceptor(httpLoggingInterceptor);
            Retrofit retrofit = new Retrofit.Builder()//
                    .client(ProgressHelper.addProgress(builder).build())//
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//
                    .addConverterFactory(GsonConverterFactory.create())//
                    .baseUrl("https://api.github.com/")//
                    .build();
            return retrofit.create(service);
        }
    }

    综合配置

    请求参数封装:

    public interface BqtService {
        @GET("User")
        Observable<BqtRes<User>> getUser();
    
        @FormUrlEncoded
        @POST("BuyInfo/buyRecord")
        Observable<BqtRes<ArrayList<MyClassBean>>> getHistory(@Field("user_id") int uid, @Field("page") int page);
    }

    调用示例:

    H.h().getUser()
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(response -> L.i("onNext " + response.data.toString());//这里response.data的类型即是User

    retrofit、okhttp、RxJava、Gson、拦截器、Header等配置

    public class H {
        private static Interceptor buildInterceptor() {
            final String token = AccountManager.getInstance().getToken();
            PackageInfo packInfo = null;
            try {
                packInfo = App.app.getPackageManager().getPackageInfo(App.app.getPackageName(), 0);
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
            final int version = packInfo == null ? 1 : packInfo.versionCode;
            return new Interceptor() {//应用程序拦截器,只被调用一次
                @Override
                public okhttp3.Response intercept(Chain chain) throws IOException {
                    Request request = chain.request()
                            .newBuilder()
                            .addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
                            .addHeader("Accept-Encoding", "gzip, deflate")
                            .addHeader("Connection", "keep-alive")
                            .addHeader("Accept", "*/*")
                            //****************************************自定义Header
                            .addHeader("version", version + "")//app版本号
                            .addHeader("token", token == null ? "" : token)//登录后返回的token
                            .addHeader("mobile", "1")// 0-PC,1-Android,2-IOS,3-web
                            .build();
                    return chain.proceed(request);
                }
            };
        }
    
        private static Interceptor buildLogInterceptor() {
            return new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
                @Override
                public void log(String message) {
                    L.d(message);//这里会打印出大量的日志出来,所以不要和手动打印的日志混在一起
                }
            }).setLevel(HttpLoggingInterceptor.Level.BODY);//日志显示级别
        }
    
        private static OkHttpClient buildOkHttp() {
            return new OkHttpClient.Builder()
                    .addInterceptor(buildHeaderInterceptor())//自定义Header
                    .addInterceptor(buildLogInterceptor())//日志拦截
                    .connectTimeout(5, TimeUnit.SECONDS)
                    .build();
        }
    
        private static Gson buildGson() {
            return new GsonBuilder()//配置你的Gson
                    .setDateFormat("yyyy-MM-dd hh:mm:ss")
                    .setPrettyPrinting()
                    .serializeNulls()
                    .create();
        }
    
        private static String buildBaseUrl() {
            switch (UrlHelper.getEnv()) {
                case 0: // baseUlr 必须以 / 结束,不然会抛出一个IllegalArgumentException
                    return "http://test.talk.99cj.com.cn/";
                case 1:
                    return "http://wechat.99cj.com.cn/";
                default:
                    return "http://wechat.99cj.com.cn/";
            }
        }
    
        private static Retrofit buildRetrofit(OkHttpClient client, Converter.Factory converterFactory, CallAdapter.Factory callAdapterFactory) {
            return new Retrofit.Builder()
                    .baseUrl(buildBaseUrl())
                    .client(client)
                    .addConverterFactory(converterFactory)//可以接收自定义的Gson,当然也可以不传
                    .addCallAdapterFactory(callAdapterFactory)
                    .build();
        }
    
        private static <T> T createRetrofitService(final Class<T> service) {
            Retrofit retrofit = buildRetrofit(buildOkHttp(), //
                    GsonConverterFactory.create(buildGson()),//
                    RxJavaCallAdapterFactory.create());//
            return retrofit.create(service);
        }
    
        public static BqtService h() {
            return createRetrofitService(BqtService.class);
        }
    }

    添加上述【HttpLoggingInterceptor】拦截器后会打印如下日志

    2017-06-20

  • 相关阅读:
    DataStructure期末复习小tips
    MediaPlayer
    Java中Calendar的用法
    C++小tips
    函数返回局部变量的问题
    framebuffer
    MTK gpio adb 控制 和 查看中断INDEX
    emmc
    No 'Access-Control-Allow-Origin' header is present on the requested resource.解决方法(亲测有效)
    JavaScript的Promise必须要会的几个点
  • 原文地址:https://www.cnblogs.com/baiqiantao/p/7054047.html
Copyright © 2011-2022 走看看