Retrofit+OkHttp+ViewModel
- 电脑硬件
- 2025-09-03 14:15:02

目录
中规中矩的 Retrofit+OkHttp+ViewModel 使用介绍。
为什么选择 LiveData、Retrofit 和 OkHttp?
项目依赖
配置 OkHttpClient 和 Retrofit
创建数据模型和 API 接口
创建 Repository 类
创建 ViewModel 类
在 Activity 中使用 ViewModel 和 LiveData
Mvvm模式使用,下面应该算是一个完整封装框架。
Retrofit Xml能力
1. 添加必要的依赖项
2. 创建数据模型
3. 创建 API 接口
4. 配置 Retrofit 实例
5. 发起请求
中规中矩的 Retrofit+OkHttp+ViewModel 使用介绍。
在现代 Android 开发中,使用 LiveData、Retrofit 和 OkHttp 进行网络请求和数据处理已经成为一种标准做法。这篇博文将详细介绍如何将这三者结合起来,构建一个高效、可维护的网络请求框架。
为什么选择 LiveData、Retrofit 和 OkHttp?LiveData:LiveData 是一种可观察的数据持有者类,具有生命周期感知能力。它能与 Android 的生命周期组件无缝集成,确保 UI 组件只在活跃状态下更新,从而避免内存泄漏和崩溃问题。
Retrofit:Retrofit 是一个强大的类型安全的 HTTP 客户端,用于 Android 和 Java。它简化了网络请求的创建和处理过程,支持多种数据转换器(如 Gson、SimpleXML),并与 OkHttp 无缝集成。
OkHttp:OkHttp 是一个高效的 HTTP 客户端,支持连接池、缓存、重定向和失败重试等功能。它为 Retrofit 提供了底层支持,并且可以通过拦截器进行灵活的请求和响应处理。
项目依赖首先,在你的 build.gradle 文件中添加以下依赖项:
dependencies { implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.okhttp3:logging-interceptor:4.9.3' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1' } 配置 OkHttpClient 和 Retrofit创建一个 ApiClient 类来配置 OkHttpClient 和 Retrofit 实例:
public class ApiClient { private static final String BASE_URL = " api.example /"; private static Retrofit retrofit = null; public static Retrofit getClient() { if (retrofit == null) { HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(logging) .build(); retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .client(client) .addConverterFactory(GsonConverterFactory.create()) .build(); } return retrofit; } } 创建数据模型和 API 接口定义一个数据模型类和一个 API 接口来描述网络请求:
public class User { @SerializedName("id") private int id; @SerializedName("name") private String name; @SerializedName("email") private String email; // Getters and Setters } public interface ApiService { @GET("users") Call<List<User>> getUsers(); } 创建 Repository 类创建一个 UserRepository 类来管理数据操作:
public class UserRepository { private ApiService apiService; public UserRepository() { apiService = ApiClient.getClient().create(ApiService.class); } public LiveData<List<User>> getUsers() { final MutableLiveData<List<User>> data = new MutableLiveData<>(); apiService.getUsers().enqueue(new Callback<List<User>>() { @Override public void onResponse(Call<List<User>> call, Response<List<User>> response) { if (response.isSuccessful()) { data.setValue(response.body()); } } @Override public void onFailure(Call<List<User>> call, Throwable t) { data.setValue(null); } }); return data; } } 创建 ViewModel 类 public class UserViewModel extends ViewModel { private UserRepository userRepository; private LiveData<List<User>> users; public UserViewModel() { userRepository = new UserRepository(); users = userRepository.getUsers(); } public LiveData<List<User>> getUsers() { return users; } } 在 Activity 中使用 ViewModel 和 LiveData在 Activity 中使用 ViewModel 和 LiveData 来观察数据变化:
public class MainActivity extends AppCompatActivity { private UserViewModel userViewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); userViewModel = new ViewModelProvider(this).get(UserViewModel.class); userViewModel.getUsers().observe(this, new Observer<List<User>>() { @Override public void onChanged(List<User> users) { // Update UI with the list of users } }); } }通过这些步骤,你可以在 Android 项目中使用 LiveData 与 Retrofit 和 OkHttp 来实现网络请求框架,并将数据绑定到 UI。这种架构设计不仅提高了代码的可读性和可维护性,还能有效地管理网络请求和数据更新。
以上就是基本使用,如果你有点追求,就是配合框架使用网络能力。
Mvvm模式使用,下面应该算是一个完整封装框架。 public class MainActivity extends BaseMvvmAc<AcMainBinding, HomeViewModel> { @Override protected int initContentView(Bundle savedInstanceState) { return R.layout.ac_main; } @Override protected int initVariableId() { return BR.viewModel; } } public abstract class BaseMvvmAc<V extends ViewDataBinding, VM extends BaseViewModel> extends BaseAc { protected VM viewModel; protected V binding; private void initViewDataBinding(Bundle savedInstanceState) { binding = DataBindingUtil.setContentView(this, initContentView(savedInstanceState)); if (viewModel == null) { Class modelClass; Type type = getClass().getGenericSuperclass(); if (type instanceof ParameterizedType) { modelClass = (Class) ((ParameterizedType) type).getActualTypeArguments()[1]; } else { //如果没有指定泛型参数,则默认使用BaseViewModel modelClass = BaseViewModel.class; } viewModel = (VM) new ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())) .get(modelClass); } if (initVariableId() > 0) { binding.setVariable(initVariableId(), viewModel); } viewModel.uiChangeLiveData().onBackPressedEvent().observe(this, o -> { onBackPressed(); }); } /** * 初始化根布局 * * @param savedInstanceState * @return 布局layout的id */ protected abstract int initContentView(Bundle savedInstanceState); /** * 初始化ViewModel的id * * @return BR的id */ protected abstract int initVariableId(); } 设置布局并获取布局实例。检查viewModel是否为空,如果为空则根据泛型参数创建对应的ViewModel实例。如果指定了ViewModel的BR id,则将ViewModel绑定到布局中。监听ViewModel中的返回按键事件,触发onBackPressed方法。 public class HomeViewModel extends BaseViewModel<HomeRepository> { public HomeViewModel(@NonNull Application application) { super(application); } } public class BaseViewModel<M extends BaseModel> extends AndroidViewModel implements IBaseViewModel, Consumer<Disposable> { private UiChangeLiveData uiChangeLiveData; private CompositeDisposable mCompositeDisposable; protected M model; public BaseViewModel(@NonNull Application application) { super(application); model = createModel(); } private M createModel() { try { Type superClass = getClass().getGenericSuperclass(); Type type = ((ParameterizedType) superClass).getActualTypeArguments()[0]; Class<?> clazz = getRawType(type); return (M) clazz.newInstance(); } catch (Exception e) { e.printStackTrace(); } return null; } //获取当前类的父类类型。 //获取父类的第一个泛型参数类型。 //将该类型转换为具体的类类型。 //使用 newInstance 方法创建该类的实例并返回。 //如果过程中出现异常,则打印堆栈信息并返回 null。 // type不能直接实例化对象,通过type获取class的类型,然后实例化对象 private Class<?> getRawType(Type type) { if (type instanceof Class) { return (Class) type; } else if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; Type rawType = parameterizedType.getRawType(); return (Class) rawType; } else if (type instanceof GenericArrayType) { Type componentType = ((GenericArrayType) type).getGenericComponentType(); return Array.newInstance(getRawType(componentType), 0).getClass(); } else if (type instanceof TypeVariable) { return Object.class; } else if (type instanceof WildcardType) { return getRawType(((WildcardType) type).getUpperBounds()[0]); } else { String className = type == null ? "null" : type.getClass().getName(); throw new IllegalArgumentException("Expected a Class, ParameterizedType, or GenericArrayType, but <" + type + "> is of type " + className); } } protected void addDisposable(Disposable disposable) { if (this.mCompositeDisposable == null) { this.mCompositeDisposable = new CompositeDisposable(); } this.mCompositeDisposable.add(disposable); } public UiChangeLiveData uiChangeLiveData() { if (uiChangeLiveData == null) { uiChangeLiveData = new UiChangeLiveData(); } return uiChangeLiveData; } @Override protected void onCleared() { super.onCleared(); if (mCompositeDisposable != null && !mCompositeDisposable.isDisposed()) { mCompositeDisposable.clear(); } if (model != null) { model.onCleared(); } } @Override public void onAny(LifecycleOwner owner, Lifecycle.Event event) { } @Override public void onCreate() { } @Override public void onDestroy() { } @Override public void onStart() { } @Override public void onStop() { } @Override public void onResume() { } @Override public void onPause() { } @Override public void accept(Disposable disposable) throws Exception { addDisposable(disposable); } public void onBackPressed() { uiChangeLiveData.onBackPressedEvent.call(); } public final class UiChangeLiveData extends SingleLiveEvent { private SingleLiveEvent<Void> onBackPressedEvent; public SingleLiveEvent<Void> onBackPressedEvent() { return onBackPressedEvent = createLiveData(onBackPressedEvent); } private <T> SingleLiveEvent<T> createLiveData(SingleLiveEvent<T> liveData) { if (liveData == null) { liveData = new SingleLiveEvent<>(); } return liveData; } } } public class HomeRepository extends BaseModel { public void unCollect(String id, ApiCallback<Object> callback) { ApiUtil.getArticleApi().unCollect(id).enqueue(callback); } } /** * Description: 不同模块BASE_URL可能不同 */ public class ApiUtil { public static ProjectApi getProjectApi() { return RetrofitCreateHelper.getInstance().create(U.BASE_URL, ProjectApi.class); } } public interface ProjectApi { /** * 项目分类 * * @return */ @RetryCount(value = 3) @GET("project/tree/json") ApiCall<List<ProjectListRes>> listProjectsTab(); } public class ApiCall <R> { private final Observable<Response<ApiResponse<R>>> mEnqueueObservable; private int mRetryCount; private long mRetryDelay; private long mRetryIncreaseDelay; private Disposable mDisposable; private Call<ApiResponse<R>> mCall; ApiCall(Annotation[] annotations, Call<ApiResponse<R>> call) { mCall = call; mEnqueueObservable = RxJavaPlugins.onAssembly(new CallEnqueueObservable<>(call)); for (Annotation annotation : annotations) { Class<? extends Annotation> clazz = annotation.annotationType(); if (clazz == RetryCount.class) { RetryCount retryCount = (RetryCount) annotation; mRetryCount = retryCount.value(); } else if (clazz == RetryDelay.class) { RetryDelay retryDelay = (RetryDelay) annotation; mRetryDelay = retryDelay.value(); } else if (clazz == RetryIncreaseDelay.class) { RetryIncreaseDelay retryIncreaseDelay = (RetryIncreaseDelay) annotation; mRetryIncreaseDelay = retryIncreaseDelay.value(); } } } /** * 进入请求队列 * 不绑定activity生命周期 * 建议使用传入activity的方式,以绑定生命周期 * * @param callback 请求回调 */ public <T extends ApiCallback<R>> void enqueue(T callback) { enqueue(null, ProgressType.NONE, false, callback); } /** * 进入请求队列 * 不绑定activity生命周期 * 建议使用传入activity的方式,以绑定生命周期 * * @param callback 请求回调 */ public <T extends ApiCallback<R>> void enqueue(T callback, ProgressType type) { enqueue(null, type, false, callback); } /** * 进入请求队列 * 无进度框,无toast * 自动绑定activity生命周期 * * @param callback 请求回调 */ public void enqueue(Context activity, final ApiCallback<R> callback) { enqueue(activity, ProgressType.NONE, false, callback); } /** * 进入请求队列 * 带可取消进度框,有toast * 自动绑定activity生命周期 * * @param callback 请求回调 */ public void enqueue2(Context activity, final ApiCallback<R> callback) { enqueue(activity, ProgressType.CANCELABLE, true, callback); } /** * 进入请求队列 * * @param activity 界面 * @param progressType 进度框类型 * @param callback 请求回调 */ public void enqueue(Context activity, ProgressType progressType, final ApiCallback<R> callback) { enqueue(activity, progressType, false, callback); } /** * 进入请求队列 * * @param activity 界面 * @param toastError 是否弹错误toast * @param callback 请求回调 */ public void enqueue(Context activity, boolean toastError, final ApiCallback<R> callback) { enqueue(activity, ProgressType.NONE, toastError, callback); } /** * 进入请求队列 * * @param activity 界面 * @param progressType 进度框类型 * @param toastError 是否弹错误toast * @param callback 请求回调 */ public void enqueue(Context activity, ProgressType progressType, final boolean toastError, final ApiCallback<R> callback) { Observable<Response<ApiResponse<R>>> observable; /*if (activity instanceof RxAppCompatActivity) { RxAppCompatActivity rxAppCompatActivity = (RxAppCompatActivity) activity; observable = mEnqueueObservable pose(rxAppCompatActivity.<Response<ApiResponse<R>>>bindToLifecycle()); } else { observable = mEnqueueObservable; }*/ observable = mEnqueueObservable; mDisposable = observable.retryWhen(new RetryHandler<R>(mRetryCount, mRetryDelay, mRetryIncreaseDelay)) .subscribeOn(Schedulers.io()) .doOnSubscribe(new Consumer<Disposable>() { @Override public void accept(Disposable disposable) throws Exception { callback.onStart(); } }) .subscribeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<Response<ApiResponse<R>>>() { @Override public void accept(Response<ApiResponse<R>> response) throws Exception { ApiResponse<R> body = response.body(); if (!response.isSuccessful() || body == null) { onError(callback, new HttpException(response), toastError); cancel(); return; } callback.onSuccess(body); cancel(); } }, new Consumer<Throwable>() { @Override public void accept(Throwable throwable) throws Exception { onError(callback, throwable, toastError); cancel(); } }); } /** * Synchronously send the request and return its response. * * @throws IOException if a problem occurred talking to the server. */ public Response<ApiResponse<R>> exectue() throws IOException { return mCall.clone().execute(); } /** * 处理错误 * * @param callback 回调 * @param throwable 错误 */ private void onError(ApiCallback<R> callback, Throwable throwable, boolean toast) { callback.onError(throwable); } public void cancel() { if (mDisposable != null) { mDisposable.dispose(); } } /** * 进度条类型 */ public enum ProgressType { /** * 无进度条 */ NONE, /** * 可取消进度条 */ CANCELABLE, /** * 不可取消进度条 */ UN_CANCELABLE } }从使用角度,直接copy以上的代码就可以。
Retrofit Xml能力 1. 添加必要的依赖项首先,在你的 build.gradle 文件中添加 Retrofit 和转换器的依赖项:
dependencies { implementation 'com.squareup.retrofit2:converter-simplexml:2.9.0' } 2. 创建数据模型创建一个数据模型类,它将被转换为 XML 格式:
@Root(name = "restrict") public class Restrict { @Attribute(name = "Type") private int type; // Constructor public Restrict(int type) { this.type = type; } // Getter and Setter public int getType() { return type; } public void setType(int type) { this.type = type; } } 3. 创建 API 接口定义一个接口来描述你的 API 端点:
public interface ApiService { @Headers({ "Content-Type: application/xml", }) @POST("xxxx") Call<Void> sendRestrict(@Body Restrict restrict); } 4. 配置 Retrofit 实例配置 Retrofit 实例并创建 API 服务:
public class RetrofitClient { private static final String BASE_URL = "xxxxxxxxx"; private static Retrofit retrofit = null; public static Retrofit getClient() { if (retrofit == null) { retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(SimpleXmlConverterFactory.create()) .build(); } return retrofit; } public static ApiService getApiService() { return getClient().create(ApiService.class); } } 5. 发起请求最后,使用创建的 ApiService 发起请求:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ApiService apiService = RetrofitClient.getApiService(); String xmlData = ""; MediaType xmlMediaType = MediaType.parse("application/xml"); RequestBody xmlBody = RequestBody.create(xmlData, xmlMediaType); Call<Void> call = apiService.sendRestrict(xmlBody); call.enqueue(new Callback<Void>() { @Override public void onResponse(Call<Void> call, Response<Void> response) { if (response.isSuccessful()) { Log.d("MainActivity", "Request successful"); } else { Log.e("MainActivity", "Request failed"); } } @Override public void onFailure(Call<Void> call, Throwable t) { Log.e("MainActivity", "Error: " + t.getMessage()); } }); } }XML请求能力主要就两点:
1、添加内置的 simplexml 依赖,添加Retrofit转换器 .addConverterFactory(SimpleXmlConverterFactory.create())
2、使用 MediaType.parse 方法定义请求体的媒体类型为 application/xml
比较简单,但是我还是在这个功能上耗费了两个小时时间差点翻车,主要是几个同事需要马上使用。按照步骤死活无法成功,
我使用的方式是 bean转 xml 请求。
String xml = "<xxx></xxx>"; Serializer serializer = new Persister(); Restrict restrict = serializer.read(Restrict.class, xml);我甚至怀疑接口是错误的,都没有怀疑这种方式有问题,用终端跑一下,成功返回数据。
然后怀疑参数问题,怀疑网络问题都没有怀疑这样的写法有什么问题。最后没办法给Okhttp添加了拦截器打印请求参数,发现 为啥是 json形式请求?说实在的至今没搞清楚为什么~
String xmlData = ""; MediaType xmlMediaType = MediaType.parse("application/xml"); RequestBody xmlBody = RequestBody.create(xmlData, xmlMediaType); if (request.body() != null && request.body().contentType() != null) { MediaType contentType = request.body().contentType(); if (contentType.subtype().equals("xml") || contentType.subtype().equals("json")) { Buffer buffer = new Buffer(); request.body().writeTo(buffer); Log.e(TAG,"Request body (" + contentType + "): " + buffer.readUtf8()); } }Retrofit+OkHttp+ViewModel由讯客互联电脑硬件栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Retrofit+OkHttp+ViewModel”