目录
中规中矩的 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 = "https://api.example.com/";
- 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 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.compose(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());
- }
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |