Android翻新电话每隔X秒
在本教程中,我们将使用Retrofit实现RxJava,以便在Android应用程序中每x秒调用一次Retrofit服务。
Android RxJava和改造
我们已经在这里一起讨论了RxJava和Retrofit的基础。
为了创建在特定时间间隔后运行的Retrofit服务,我们可以使用以下命令:
- 处理程序
- RxJava的
处理程序用于将数据从后台线程传递/传递到UI线程
使用RxJava,我们可以使用RxJava运算符做更多的事情,而且非常容易。
在每个给定的时间段之后,我们可以使用时间间隔运算符来调用某个方法(在本例中为翻新网络调用)。
" Observable.interval"运算符用于在特定间隔后发出值。
看起来像这样:
Observable.interval(1000, 5000, TimeUnit.MILLISECONDS);
1000是发射开始之前的初始延迟,每5秒重复一次。
我们可以订阅观察者,该观察者每5秒调用一次Retrofit方法。
在某些时间间隔后调用翻新服务在提供实时更新的应用程序中非常普遍,例如板球得分应用程序等。
在下一部分中,让我们开始实施。
我们将创建一个应用程序,该应用程序每5秒就会在TextView中显示一个新的随机笑话。
项目结构
将以下依赖项添加到build.gradle文件:
implementation('com.squareup.retrofit2:retrofit:2.3.0') { exclude module: 'okhttp' } implementation 'io.reactivex.rxjava2:rxjava:2.1.9' implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' implementation 'io.reactivex.rxjava2:rxandroid:2.0.1' implementation 'com.squareup.okhttp3:logging-interceptor:3.9.1'
为了使用lambda语法,请确保在build.gradle的android块内将编译选项设置为以下内容。
android { ... compileOptions { targetCompatibility 1.8 sourceCompatibility 1.8 } ... }
代码
下面给出了activity_main.xml布局的代码:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:app="https://schemas.android.com/apk/res-auto" xmlns:tools="https://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:padding="16dp" android:text="See this space for more jokes..." app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="24dp" android:text="JOKES BELOW...." android:textAppearance="@style/Base.TextAppearance.AppCompat.Headline" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" </android.support.constraint.ConstraintLayout>
我们将使用以下公共API:https://api.chucknorris.io/jokes/random。
创建定义了API的APIService.java类:
package com.theitroad.androidretrofitcalleveryxsecond; import io.reactivex.Observable; import retrofit2.http.GET; import retrofit2.http.Path; public interface APIService { String BASE_URL = "https://api.chucknorris.io/jokes/"; @GET("{path}") Observable<Jokes> getRandomJoke(@Path("path") String path); }
以下是Jokes.java类的POJO模型:
package com.theitroad.androidretrofitcalleveryxsecond; import com.google.gson.annotations.SerializedName; import java.util.List; public class Jokes { @SerializedName("url") public String url; @SerializedName("icon_url") public String icon_url; @SerializedName("value") public String value; }
MainActivity.java的代码如下:
package com.theitroad.androidretrofitcalleveryxsecond; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.TextUtils; import android.widget.TextView; import android.widget.Toast; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.util.concurrent.TimeUnit; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; import okhttp3.OkHttpClient; import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Retrofit; import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; import static com.theitroad.androidretrofitcalleveryxsecond.APIService.BASE_URL; public class MainActivity extends AppCompatActivity { Retrofit retrofit; TextView textView; APIService apiService; Disposable disposable; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = findViewById(R.id.textView); HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(interceptor) .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .build(); Gson gson = new GsonBuilder() .setLenient() .create(); retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .client(client) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create(gson)) .build(); apiService = retrofit.create(APIService.class); disposable = Observable.interval(1000, 5000, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::callJokesEndpoint, this::onError); } @Override protected void onResume() { super.onResume(); if (disposable.isDisposed()) { disposable = Observable.interval(1000, 5000, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::callJokesEndpoint, this::onError); } } private void callJokesEndpoint(Long aLong) { Observable<Jokes> observable = apiService.getRandomJoke("random"); observable.subscribeOn(Schedulers.newThread()). observeOn(AndroidSchedulers.mainThread()) .map(result -> result.value) .subscribe(this::handleResults, this::handleError); } private void onError(Throwable throwable) { Toast.makeText(this, "OnError in Observable Timer", Toast.LENGTH_LONG).show(); } private void handleResults(String joke) { if (!TextUtils.isEmpty(joke)) { textView.setText(joke); } else { Toast.makeText(this, "NO RESULTS FOUND", Toast.LENGTH_LONG).show(); } } private void handleError(Throwable t) { //Add your error here. } @Override protected void onPause() { super.onPause(); disposable.dispose(); } }
setLenient()用于防止错误的JSON响应异常。
当用户离开活动时,该一次性实例将取消订阅。
在onResume方法中再次创建Observable流之前,请检查Disposable中的isDisposed
方法。