前言:
首先了解Retrofit注解,以下注解本人都会讲到.
1、首先在Android项目中引入需要的依赖
implementation 'com.github.bumptech.glide:glide:4.8.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
2、创建一个单例类,返回Retrofit对象
public class RetrofitManager { private RetrofitManager() { } /** * 1.首先使用Retrofit.Builder来构建一个Retrofit对象, * 2.baseUrl()方法用于指定所有Retrofit请求的根路径 * 3.addConverterFactory()方法用于指定Retrofit在解析数据时所使用的转换库,这里指定成GsonConverterFactory * 用的是Gson库 */ public static Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://192.168.5.171:9102") .addConverterFactory(GsonConverterFactory.create()) .build(); public static Retrofit getRetrofit() { return retrofit; } }
3、创建对应的接口Api,写对应的请求方法和参数
public interface Api { @GET("/get/text") Call<JsonResult> getJson(); @GET("/get/param") Call<ParamModel> getParam(@Query("keyword") String keyword, @Query("page") int page, @Query("order") int order); @GET("/get/param") Call<ParamModel> getParamQueryMap(@QueryMap Map<String, Object> queryMap); @POST("/post/string") Call<PostParamModel> getPostQuery(@Query("string") String string); @POST Call<PostParamModel> postParamUrl(@Url String url); @POST("/post/comment") Call<PostParamModel> postWithBody(@Body CommentBody body); /** * @Part 和 @Multipart结合使用 一般用于上传文件 */ @Multipart @POST("/file/upload") Call<PostParamModel> postUploadFile(@Part MultipartBody.Part part, @Header("token") String token); /** * @Part 和 @Multipart结合使用 一般用于上传文件 */ @Headers({"token:398429865hdsfhaj", "client:Android", "version:1.1.0"}) @Multipart @POST("/files/upload") Call<PostParamModel> postUploadFiles(@Part ArrayList<MultipartBody.Part> parts); /** * @PartMap 一般用于上传文件和参数时使用。 */ @Multipart @POST("/file/params/upload") Call<PostParamModel> postUploadFileWithParams(@Part MultipartBody.Part part, @PartMap Map<String, Object> map, @HeaderMap Map<String, String> headerMap); @FormUrlEncoded @POST("/login") Call<PostParamModel> postLogin(@Field("userName") String userName, @Field("password") String password); @FormUrlEncoded @POST("/login") Call<PostParamModel> postLoginFileMap(@FieldMap Map<String, String> fieldMap); @Streaming @GET Call<ResponseBody> downloadFile(@Url String url); }
4、创建对应的activity_request.xml
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="presenter" type="com.example.customview.retrofit.RequestActivity.Presenter" /> </data> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:id="@+id/btn_request" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{()->presenter.getWithParams()}" android:text="getWithParams-@Query" android:textAllCaps="false" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/btn_request_query_map" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{()->presenter.getWithParamsQueryMap()}" android:text="getWithParams-@QueryMap" android:textAllCaps="false" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/btn_request" /> <Button android:id="@+id/btn_post_query" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{()->presenter.postParamQuery()}" android:text="postWithParam-@Query" android:textAllCaps="false" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/btn_request_query_map" /> <Button android:id="@+id/btn_post_url" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{()->presenter.postParamUrl()}" android:text="postWithParam-@Url" android:textAllCaps="false" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/btn_post_query" /> <Button android:id="@+id/btn_post_body" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{()->presenter.postWithBody()}" android:text="postWithBody-@Body" android:textAllCaps="false" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/btn_post_url" /> <Button android:id="@+id/btn_post_file" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{()->presenter.postUploadFile()}" android:text="postUploadFile" android:textAllCaps="false" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/btn_post_body" /> <Button android:id="@+id/btn_post_files" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{()->presenter.postUploadFiles()}" android:text="postUploadFiles" android:textAllCaps="false" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/btn_post_file" /> <Button android:id="@+id/btn_post_file_param" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{()->presenter.postUploadFileParams()}" android:text="postUploadFileParams" android:textAllCaps="false" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/btn_post_files" /> <Button android:id="@+id/btn_post_login" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{()->presenter.postLogin()}" android:text="postLogin-@Field" android:textAllCaps="false" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/btn_post_file_param" /> <Button android:id="@+id/btn_post_login_filed_map" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{()->presenter.postLoginFiledMap()}" android:text="postUploadFileParams-@FieldMap" android:textAllCaps="false" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/btn_post_login" /> <Button android:id="@+id/btn_post_down_load" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{()->presenter.downFile()}" android:text="downFile" android:textAllCaps="false" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/btn_post_login_filed_map" /> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
5、在对应的Activity进行编码,注释已经给出
/** * @Author: ly * @Date: 2023/2/24 * @Description: Retrofit的使用 */ public class RequestActivity extends AppCompatActivity { private static final String TAG = "RequestActivity"; private ActivityRequestBinding binding; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding = DataBindingUtil.setContentView(this, R.layout.activity_request); binding.setPresenter(new Presenter()); } private Api getApi() { Retrofit retrofit = RetrofitManager.getRetrofit(); return retrofit.create(Api.class); } public class Presenter { /** * get请求,请求参数为@Query */ public void getWithParams() { //1.创建retrofit对象 Api api = getApi(); //3.当调用了Api.getParam()方法,就回返回Call<ParamModel>对象 Call<ParamModel> call = api.getParam("测试", 10, 1); /** * 之后们再调用一下它的enqueue()方法Retrofit就会根据注解 * 中配置的服务器接口地址去进行网络请求了,服务器响应的数据会回调到enqueue()方法中传 * 入的Callback实现里面。需要注意的是,当发起请求的时候,Retrofit会自动在内部开启子线 * 程,当数据回调到Callback中之后,Retrofit又会自动切换回主线程,整个操作过程中我们都 * 不用考虑线程切换问题。在Callback的onResponse()方法中,调用response.body()方 * 法将会得到Retrofit解析后的对象,也就是ParamModel类型的数据。 */ call.enqueue(new Callback<ParamModel>() { @Override public void onResponse(Call<ParamModel> call, Response<ParamModel> response) { if (response.code() == HttpURLConnection.HTTP_OK) { Log.i(TAG, "getWithParams: " + response.body()); } } @Override public void onFailure(Call<ParamModel> call, Throwable t) { } }); } /** * get请求,请求参数为@QueryMap */ public void getWithParamsQueryMap() { Api api = getApi(); Map<String, Object> map = new HashMap<>(); map.put("keyword", "关键字"); map.put("page", 10); map.put("order", 0); Call<ParamModel> call = api.getParamQueryMap(map); call.enqueue(new Callback<ParamModel>() { @Override public void onResponse(Call<ParamModel> call, Response<ParamModel> response) { Log.i(TAG, "getWithParamsQueryMap: " + response.body()); } @Override public void onFailure(Call<ParamModel> call, Throwable t) { } }); } /** * post请求,请求参数为@Query */ public void postParamQuery() { Api api = getApi(); Call<PostParamModel> call = api.getPostQuery("测试的新数据"); call.enqueue(new Callback<PostParamModel>() { @Override public void onResponse(Call<PostParamModel> call, Response<PostParamModel> response) { if (response.code() == HttpsURLConnection.HTTP_OK) { Log.i(TAG, "postParamQuery: " + response.body()); } } @Override public void onFailure(Call<PostParamModel> call, Throwable t) { } }); } /** * post请求,请求参数为@Url */ public void postParamUrl() { String url = "post/string?string=Android开发"; Api api = getApi(); Call<PostParamModel> call = api.postParamUrl(url); call.enqueue(new Callback<PostParamModel>() { @Override public void onResponse(Call<PostParamModel> call, Response<PostParamModel> response) { if (response.code() == HttpsURLConnection.HTTP_OK) { Log.i(TAG, "postParamUrl: " + response.body()); } } @Override public void onFailure(Call<PostParamModel> call, Throwable t) { Log.i(TAG, "postParamUrl: " + t.toString()); } }); } /** * post请求,请求参数注解@Body */ public void postWithBody() { Api api = getApi(); CommentBody body = new CommentBody("45651", "这条评论非常不错!"); Call<PostParamModel> call = api.postWithBody(body); call.enqueue(new Callback<PostParamModel>() { @Override public void onResponse(Call<PostParamModel> call, Response<PostParamModel> response) { if (response.code() == HttpURLConnection.HTTP_OK) { Log.i(TAG, "postWithBody: " + response.body()); } } @Override public void onFailure(Call<PostParamModel> call, Throwable t) { } }); } /** * post请求,进行单文件上传 */ public void postUploadFile() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (ContextCompat.checkSelfPermission(RequestActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageInfo.REQUESTED_PERMISSION_GRANTED || ContextCompat.checkSelfPermission(RequestActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageInfo.REQUESTED_PERMISSION_GRANTED ) { requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 200); } else { InputPicture(); } } else { InputPicture(); } } /** * post请求,进行多文件上传 */ public void postUploadFiles() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (ContextCompat.checkSelfPermission(RequestActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageInfo.REQUESTED_PERMISSION_GRANTED || ContextCompat.checkSelfPermission(RequestActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageInfo.REQUESTED_PERMISSION_GRANTED ) { requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 300); } else { postUploadImages(); } } else { postUploadImages(); } } /** * 文件上传并携带参数 */ public void postUploadFileParams() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (ContextCompat.checkSelfPermission(RequestActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageInfo.REQUESTED_PERMISSION_GRANTED || ContextCompat.checkSelfPermission(RequestActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageInfo.REQUESTED_PERMISSION_GRANTED ) { requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 400); } else { postUploadImageParams(); } } else { postUploadImageParams(); } } /** * 登录 */ public void postLogin() { Call<PostParamModel> call = getApi().postLogin("Android开发", "a123456"); call.enqueue(new Callback<PostParamModel>() { @Override public void onResponse(Call<PostParamModel> call, Response<PostParamModel> response) { if (HttpURLConnection.HTTP_OK == response.code()) { Log.i(TAG, "postLogin: " + response.body()); } } @Override public void onFailure(Call<PostParamModel> call, Throwable t) { Log.i(TAG, "onFailure: " + t.toString()); } }); } /** * post请求进行登录,请求参数注解为@FieldMap */ public void postLoginFiledMap() { Map<String, String> map = new HashMap<>(); map.put("userName", "Android开发者"); map.put("password", "a123456789"); Call<PostParamModel> call = getApi().postLoginFileMap(map); call.enqueue(new Callback<PostParamModel>() { @Override public void onResponse(Call<PostParamModel> call, Response<PostParamModel> response) { if (HttpURLConnection.HTTP_OK == response.code()) { Log.i(TAG, "onResponse: " + response.body()); } } @Override public void onFailure(Call<PostParamModel> call, Throwable t) { Log.i(TAG, "onResponse: " + t.toString()); } }); } /** * 文件下载 */ public void downFile() { Call<ResponseBody> call = getApi().downloadFile("/download/11"); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { if (HttpURLConnection.HTTP_OK == response.code()) { ResponseBody body = response.body(); //要知道文件名称 Headers headers = response.headers(); String fileNameHeader = headers.get("Content-disposition"); String fileName = "未命名.png"; if (fileName != null) { fileName = fileNameHeader.replace("attachment; filename=", ""); Log.i(TAG, "fileName: " + fileName); } writeToDisk(response, fileName); // for (int i = 0; i < headers.size(); i++) { // String key = headers.name(i); // String value = headers.value(i); // Log.i(TAG, "key: " + key + " name:" + value); // /** // * 数据结果 // * key: Content-disposition name:attachment; filename=12.png // * key: Content-Type name:application/x-msdownload // * key: Content-Length name:66885 // * key: Date name:Sat, 25 Feb 2023 08:11:04 GMT // */ // } } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { Log.i(TAG, "onFailure: " + t.toString()); } }); } } /** * 下载的文件写入到指定的文件中 * * @param response * @param fileName */ private void writeToDisk(Response<ResponseBody> response, String fileName) { String finalFileName = fileName; new Thread(() -> { InputStream inputStream = response.body().byteStream(); File file = getExternalFilesDir(Environment.DIRECTORY_PICTURES); File outFile = new File(file, finalFileName); Log.i(TAG, "file: " + file); FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(outFile); byte[] bytes = new byte[1024]; int len = 0; while ((len = inputStream.read(bytes)) != -1) { fileOutputStream.write(bytes, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { try { fileOutputStream.close(); } catch (Exception e) { e.printStackTrace(); } } }).start(); } /** * 文件上传携带参数 */ private void postUploadImageParams() { MultipartBody.Part part = createMultipartBodyPart("/sdcard/DCIM/Screenshots/Screenshot_2023-02-25-10-39-00-40_6ea35cac63846bc763be64f446db684d.jpg", "file"); Map<String, Object> map = new HashMap<>(); map.put("description", "这是筱路上传的图片"); map.put("isFree", true); Map<String, String> headerMap = new HashMap<>(); headerMap.put("token", "11111111111111111"); headerMap.put("client", "iPhone20"); headerMap.put("version", "1.0.2"); Call<PostParamModel> call = getApi().postUploadFileWithParams(part, map, headerMap); call.enqueue(new Callback<PostParamModel>() { @Override public void onResponse(Call<PostParamModel> call, Response<PostParamModel> response) { if (HttpURLConnection.HTTP_OK == response.code()) { Log.i(TAG, "postUploadImageParams: " + response.body()); } } @Override public void onFailure(Call<PostParamModel> call, Throwable t) { Log.i(TAG, "onFailure: " + t.toString()); } }); } /** * 多文件上传 */ private void postUploadImages() { ArrayList<MultipartBody.Part> parts = new ArrayList<>(); MultipartBody.Part partOne = createMultipartBodyPart("/sdcard/DCIM/Screenshots/Screenshot_2023-02-04-15-01-55-68_abc7e8e26578fbac9cdf97e1ea2cd1b5.jpg", "files"); parts.add(partOne); MultipartBody.Part partTwo = createMultipartBodyPart("/sdcard/DCIM/Screenshots/Screenshot_2023-02-20-18-19-34-49.jpg", "files"); parts.add(partTwo); MultipartBody.Part partThree = createMultipartBodyPart("/sdcard/DCIM/Screenshots/Screenshot_2023-02-25-10-39-00-40_6ea35cac63846bc763be64f446db684d.jpg", "files"); parts.add(partThree); Api api = getApi(); Call<PostParamModel> call = api.postUploadFiles(parts); call.enqueue(new Callback<PostParamModel>() { @Override public void onResponse(Call<PostParamModel> call, Response<PostParamModel> response) { Log.i(TAG, "code: " + response.code()); if (HttpURLConnection.HTTP_OK == response.code()) { Log.i(TAG, "postUploadImages: " + response.body()); } } @Override public void onFailure(Call<PostParamModel> call, Throwable t) { Log.i(TAG, "onFailure: " + t.toString()); } }); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 200) { InputPicture(); Log.i(TAG, "onRequestPermissionsResult: "); } else if (requestCode == 300) { postUploadImages(); } else if (requestCode == 400) { postUploadImageParams(); } } /** * 单文件上传 * * @param picturePath 图片路径 */ private void postUploadImage(String picturePath) { Api api = getApi(); MultipartBody.Part part = createMultipartBodyPart(picturePath, "file"); Call<PostParamModel> call = api.postUploadFile(part, "asfsafklio349823727859"); call.enqueue(new Callback<PostParamModel>() { @Override public void onResponse(Call<PostParamModel> call, Response<PostParamModel> response) { if (response.code() == HttpURLConnection.HTTP_OK) { Log.i(TAG, "postUploadFile: " + response.body()); } } @Override public void onFailure(Call<PostParamModel> call, Throwable t) { Log.i(TAG, "onFailure: " + t.toString()); } }); } private MultipartBody.Part createMultipartBodyPart(String picturePath, String key) { File file = new File(picturePath); RequestBody body = RequestBody.create(MediaType.parse("image/jpg"), file); return MultipartBody.Part.createFormData(key, file.getName(), body); } private void InputPicture() { //Intent.ACTION_PICK 从数据中选择一个项目 (item),将被选中的项目返回。 //MediaStore.Images.Media.EXTERNAL_CONTENT_URI 获取外部的URI Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); //参数一:对应的数据的URI 参数二:使用该函数表示要查找文件的MIME类型 intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*"); startActivityForResult(intent, 1); } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 1 && resultCode == RESULT_OK && null != data) { Uri selectedImage = data.getData(); String[] filePathColumn = {MediaStore.Images.Media.DATA}; Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null); cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex(filePathColumn[0]); String picturePath = cursor.getString(columnIndex); Log.e("TAG", "onActivityResult: " + picturePath); postUploadImage(picturePath); } } }
对应的Model就不给出了,需要的可以私信我要。