zoukankan      html  css  js  c++  java
  • HTTP Retrofit 网络传输

    原文:https://www.jianshu.com/p/0fda3132cf98

    Retrofit注解

    • 请求方法
    注解代码请求格式
    @GET GET请求
    @POST POST请求
    @DELETE DELETE请求
    @HEAD HEAD请求
    @OPTIONS OPTIONS请求
    @PATCH PATCH请求
    • 请求参数
    注解代码说明
    @Headers 添加请求头
    @Path 替换路径
    @Query 替代参数值,通常是结合get请求的
    @FormUrlEncoded 用表单数据提交
    @Field 替换参数值,是结合post请求的

    前提:

    Android 系统上面默认所有Http的请求都被阻止了。

    需要在androidmanifest.xml的 application标签上加入 android:usesCleartextTraffic="true"

    首先引入依赖:Gson可以将Json和基本数据类型之间做转换;Okhtttp用来进行HTTP连接(Retrofit就是建立在OkHttp之上的);ReJava用来提供一个异步处理的操作。

    //Gson库
    implementation 'com.google.code.gson:gson:2.8.2'
    // Okhttp库
    implementation 'com.squareup.okhttp3:okhttp:3.1.2'
    // Retrofit库
    implementation 'com.squareup.retrofit2:retrofit:2.0.2'
    implementation 'com.squareup.retrofit2:converter-gson:2.0.2'  //gson转化
    implementation 'com.squareup.retrofit2:adapter-rxjava:2.0.2'  //RxJava
    //RxJava库
    implementation 'io.reactivex:rxandroid:1.0.1'

    先看下服务端代码,其实就是接收到了连接后返回一个JSON格式的数据:

    var http = require('http');
    var url = require('url');
    var util = require('util');
     
    http.createServer(function(req, res){
        res.writeHead(200, {'Content-Type': 'text/plain'});
        // 解析 url 参数
        var params = url.parse(req.url, true).query;
        console.log("有连接");
        console.log(util.inspect(url.parse(req.url, true)));
        //发送JSON数据
        var jsonobj = {time:0, code:1, data:{song_url:'yangzhilong_tem.mp3', msg:123}};
        res.end(JSON.stringify(jsonobj));
    }).listen(3000);

    先定义一个Bean来表示从服务端获取到的东西:

    import java.util.Map;
    public class User {
        private long time;
        private int code;
        private Map<String, String> data;
    
        public Map<String, String> getData() {
            return data;
        }
        public int getCode() {
            return code;
        }
        public long getTime() {
            return time;
        }
    }

    定义一个接口来提供服务:

    import retrofit2.http.GET;
    import retrofit2.http.Query;
    import rx.Observable;
    public interface GetAPI {
        //设置路径    
        @GET("create/original")
        Observable<User> getUser(@Query("author_id") String author_id, @Query("type") String type, @Query("info") String info);
    }

    java代码:

    package com.example.m_evolution;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    
    import com.example.m_evolution.Bean.User;
    import com.example.m_evolution.HttpAPI.GetAPI;
    import java.util.concurrent.TimeUnit;
    
    import okhttp3.OkHttpClient;
    import retrofit2.Retrofit;
    import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
    import retrofit2.converter.gson.GsonConverterFactory;
    import rx.Subscriber;
    import rx.android.schedulers.AndroidSchedulers;
    import rx.schedulers.Schedulers;
    
    public class TestActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_test);
    
            OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
                .build();
    
            Retrofit retrofit = new Retrofit.Builder()
                //设置数据解析器
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                //设置网络请求的Url地址
                .baseUrl("http://172.17.1.96:3000/")
                .client(okHttpClient)
                .build();
    
            // 创建网络请求接口的实例
            GetAPI mApi = retrofit.create(GetAPI.class);
    
            mApi.getUser("1", "10", "[嘻哈,兴奋]")
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<User>() {
                    @Override
                    public void onCompleted() {
                        Log.d("TestActivity", "调用完成");
                    }
    
                    @Override
                    public void onError(Throwable e) {
                        Log.d("TestActivity", "请求失败"+e.toString());
                    }
    
                    @Override
                    public void onNext(User user) {
                        Log.d("TestActivity", "请求成功");
                        Log.d("TestActivity", "time:"+user.getTime());
                        Log.d("TestActivity", "code:"+user.getCode());
                        Log.d("TestActivity", "song_url:"+user.getData().get("song_url")+"; msg:"+user.getData().get("msg"));
                    }
                });
        }
    }

    客户端结果:

    服务端结果:

     GET请求:

    服务端提供的接口:

    客户端:

        //获取某用户的信息
        @GET("/user/info")
        Observable<UserInfoHTTPResult> get_user_info(@Header("Authorization")String token, @Query("user_id")String user_id);
    public class UserInfoHTTPResult {
        private long time;  //服务器响应时间
        private int code;  //响应码 0表示正常
        private String msg;  //错误信息
        private Map<String, String> data;
    
        public long getTime() {
            return time;
        }
        public int getCode() {
            return code;
        }
        public String getMsg() {
            return msg;
        }
        public String getUserName(){
            return data.get("username");
        }
        public String getGender(){
            return data.get("gender");
        }
        public String getAvatarUrl(){
            return data.get("avatar");
        }
    }
    httpAPI.get_user_info(MyApp.token_pre+myApp.getUser_token(), user_id)
                        .subscribeOn(Schedulers.newThread())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Subscriber<UserInfoHTTPResult>() {
                            @Override
                            public void onCompleted() {
                                Log.d(TAG, "onCompleted: "+"调用完成");
                            }
    
                            @Override
                            public void onError(Throwable e) {
                                Log.d(TAG, "onError: "+"请求失败: "+e.toString());
                                myApp.MakeToast("网络出错");
                            }
    
                            @Override
                            public void onNext(UserInfoHTTPResult userInfoHTTPResult) {
                                if(userInfoHTTPResult.getCode()==0){
                                    //更新个人信息
                                    myApp.setUser_nickname(userInfoHTTPResult.getUserName());
                                    myApp.setUser_gender(userInfoHTTPResult.getGender());
                                    myApp.setUser_head_url(userInfoHTTPResult.getAvatarUrl());
                                    Log.d(TAG, "onNext: username: "+myApp.getUser_nickname());
                                    Log.d(TAG, "onNext: gender: "+myApp.getUser_gender());
                                    Log.d(TAG, "onNext: avatar: "+myApp.getUser_head_url());
                                    editor.putString("user_nickname",myApp.getUser_nickname());
                                    editor.putString("user_gender",myApp.getUser_gender());
                                    editor.putString("user_head_url", myApp.getUser_head_url());
                                    editor.commit();
                                    //修改控件
                                    tv_user_nickname.setText(userInfoHTTPResult.getUserName());
                                    if(myApp.getUser_gender().equals("female")){
                                        iv_user_gender.setImageResource(R.drawable.icon_user_gender_female);
                                    }
                                    else{
                                        iv_user_gender.setImageResource(R.drawable.icon_user_gender_male);
                                    }
                                    ImageLoader.getInstance().displayImage(MyApp.baseUrl+myApp.getUser_head_url(),iv_user_head);
                                }
                            }
                        });

     POST请求:

    服务端提供的接口:

    注意,最后一个参数avatar表示头像,涉及到文件的上传;

        //用户更新信息
        @Multipart
        @POST("/update/user")
        Observable<UpdateUserHTTPResult> update_user(@Header("Authorization")String token, @Part("user_id") RequestBody user_id, @Part("username")RequestBody user_nickname, @Part("gender")RequestBody gender, @Part MultipartBody.Part part_head);
    public class UpdateUserHTTPResult {
        private long time;  //服务器响应时间
        private int code;  //响应码 0表示正常
        private String msg;  //错误信息
        private Map<String, String> data;
    
        public long getTime() {
            return time;
        }
        public int getCode() {
            return code;
        }
        public String getMsg() {
            return msg;
        }
        public String getIsok(){
            return data.get("isok");
        }
        public String getAvatar_url(){
            return data.get("avatar_url");
        }
    }
    RequestBody requestUserID = RequestBody.create(MediaType.parse("multipart/form-data"), user_id);
                RequestBody requestUserNickname = RequestBody.create(MediaType.parse("multipart/form-data"), user_nickname);
                RequestBody requestGender = RequestBody.create(MediaType.parse("multipart/form-data"), gender);
                //将头像图片存储为图片
                Bitmap bitmap = ((BitmapDrawable)iv_user_head.getDrawable()).getBitmap();
                ImageUtils.saveImage(bitmap, "temp.png");
                // 创建RequestBody,传入参数:"multipart/form-data",File
                File imgFile = new File(Environment.getExternalStorageDirectory(),getString(R.string.app_name)+"/temp.png");
                RequestBody fileRequestBody = RequestBody.create(MediaType.parse("multipart/form-data"), imgFile);
                // 创建MultipartBody.Part,用于封装文件数据
                MultipartBody.Part requestImgPart = MultipartBody.Part.createFormData("avatar", imgFile.getName(), fileRequestBody);
                httpAPI.update_user("Bearer "+myApp.getUser_token(),requestUserID, requestUserNickname, requestGender, requestImgPart)
                        .subscribeOn(Schedulers.newThread())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Observer<UpdateUserHTTPResult>() {
                            @Override
                            public void onCompleted() {
                                Log.d(TAG, "onCompleted: ");
                                dialog_busying.dismiss();
                            }
    
                            @Override
                            public void onError(Throwable e) {
                                Log.d(TAG, "onError: "+e.toString());
                                myApp.MakeToast("网络出错");
                                dialog_busying.dismiss();
                            }
    
                            @Override
                            public void onNext(UpdateUserHTTPResult updateUserHTTPResult) {
                                Log.d(TAG, "onNext: Time "+updateUserHTTPResult.getTime());
                                Log.d(TAG, "onNext: Code "+updateUserHTTPResult.getCode());
                                Log.d(TAG, "onNext: Msg "+updateUserHTTPResult.getMsg());
                                Log.d(TAG, "onNext: Isok "+updateUserHTTPResult.getIsok());
                                Log.d(TAG, "onNext: Avatar_url "+updateUserHTTPResult.getAvatar_url());
                                if(updateUserHTTPResult.getIsok().equals("true")){  //如果保存成功
                                    //更新本地的用户昵称
                                    String user_nickname = et_user_nickname.getText().toString();
                                    myApp.setUser_nickname(user_nickname);
                                    myApp.setUser_head_url(updateUserHTTPResult.getAvatar_url());
                                    if (selector_gender == 0) myApp.setUser_gender("male");
                                    else if (selector_gender == 1) myApp.setUser_gender("female");
                                    editor.putString("user_nickname", myApp.getUser_nickname());
                                    editor.putString("user_head_url", myApp.getUser_head_url());
                                    editor.putString("user_gender",myApp.getUser_gender());
                                    editor.commit();
                                    myApp.MakeToast("保存成功");
                                    Log.d(TAG, "onNext: 保存成功");
                                    EventBus.getDefault().post("change_user_info");
                                }
                                else{
                                    myApp.MakeToast("保存失败");
                                    Log.d(TAG, "onNext: 保存失败");
                                }
                                dialog_busying.dismiss();
                            }
                        });

    上面是表单上传数据,如果是要JSON上传数据,则:

    interface APIStore {
       @Headers({"Content-Type: application/json","Accept: application/json"})//需要添加头
       @POST ("vdyweb/ws/rest/Login")
       Call<ResponseBody>getMessage(@Body RequestBody info);   // 请求体味RequestBody 类型

    PS:这里的数据类型是@Body,与表单不同

    public class Info {
        String account;
        String password;
     
        public Info(String account, String password) {
            this.account = account;
            this.password = password;
        }
    }
    Info info=new Info("test","123456");   /*** 利用Gson 将对象转json字符串*/
    Gson gson=new Gson();
    String obj=gson.toJson(info);
    retrofit=new Retrofit.Builder().baseUrl(BASE_LOGIN_URL).build();
    RequestBody body=RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),obj);
  • 相关阅读:
    Centos 7 运行出错:cannot find a valid basecrl for repo:base/7/x86_64
    nc 使用
    linux uniq去重,awk输出(可用于爆破字典优化)
    关于fixedsys字体 FSEX300.ttf FSEX300-L.ttf FSEX301-L2.ttf
    MyAtoi
    viplugin eclipse
    资源获取即初始化RAII
    阈值分割技术
    图像类型转换
    形态学
  • 原文地址:https://www.cnblogs.com/zhaozilongcjiajia/p/10794946.html
Copyright © 2011-2022 走看看