我正在使用dagger 2为okhttp3创建模块。现在我想检查网络模块内的互联网连接。实现这一目标的最佳方法是什么?
答案 0 :(得分:3)
查看任何answers to this canonical question并简单地封装它们。
例如,您可以使用如下界面:
public interface OnlineChecker {
boolean isOnline();
}
然后最受欢迎的实施:
public class DefaultOnlineChecker implements OnlineChecker {
private final ConnectivityManager connectivityManager;
public DefaultOnlineChecker(ConnectivityManager connectivityManager) {
this.connectivityManager = connectivityManager;
}
@Override
public boolean isOnline() {
NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
return netInfo != null && netInfo.isConnectedOrConnecting();
}
}
第二个最受欢迎的实施:
public class ExperimentalOnlineChecker implements OnlineChecker {
private final Runtime runtime;
public ExperimentalOnlineChecker(Runtime runtime) {
this.runtime = runtime;
}
@Override
public boolean isOnline() {
try {
Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
int exitValue = ipProcess.waitFor();
return (exitValue == 0);
}
catch (IOException e) { e.printStackTrace(); }
catch (InterruptedException e) { e.printStackTrace(); }
return false;
}
}
然后在它自己的模块或其他地方绑定你想要的实现:
@Module
public class OnlineCheckerModule {
@Provides
public OnlineChecker onlineChecker() {
Runtime runtime = Runtime.getRuntime();
return new ExperimentalOnlineChecker(runtime);
}
}
现在在您的Activity或Fragment中,您只需使用属性注入注入:
@Inject OnlineChecker onlineChecker;
@Override
protected void onCreate(Bundle savedInstanceState) {
super(savedInstanceState);
//perform injection with Dagger 2 and then you can use your
//OnlineChecker
}
答案 1 :(得分:1)
对于遵循 MVVM 或 Kotlin协程(非必要)且在 api 22 以上的用户,这里是:
使用 Dagger Android 和 MVVM 的新实现。
在深入研究之前,您的匕首类图或对象图已经设置好,然后您必须执行以下操作:
ConnectivityInterceptor界面
interface ConnectivityInterceptor : Interceptor
ConnectivityInterceptorImpl
您可以使用Custom Exception类,也可以只使用 IOException
要检查移动设备的互联网连接状态,您必须使用连接管理器,当然还要从清单中启用网络状态
在 isOnline()中,有些东西已弃用了 api 28 或 api 29 ,如果api无法使用某些方法级别低于 22 ,因此我使用了当前状态,如果您高于api 22
class ConnectivityInterceptorImpl (
private var application: Application
) : ConnectivityInterceptor {
override fun intercept(chain: Interceptor.Chain): Response {
if (!isOnline())
throw NoConnectivityException() //custom Exception class
return chain.proceed(chain.request())
}
private fun isOnline(): Boolean {
val connectivityManager = application.getSystemService(
Context.CONNECTIVITY_SERVICE
) as ConnectivityManager
var res = false
connectivityManager.let {
it.getNetworkCapabilities(connectivityManager.activeNetwork)?.apply {
res = when {
hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
else -> false
}
}
}
return res
}
}
Dagger AppModule
匕首来了:
由于我们使用 Interceptor 来获取网络状态,因此当然会在 okHttpClient 中充当拦截器,并且在这里使用Okkhttp进行后面的网络调用retrofitBuilder(),这意味着我们正在执行名为 Singleton 的操作,因此在这种情况下,我们必须管理Dagger的对象图
@Module
abstract class AppModule {
@Module
companion object {
@JvmStatic
@Singleton
@Provides
fun providesConnectivityInterceptorImpl(application: Application):
ConnectivityInterceptorImpl {
return ConnectivityInterceptorImpl(application)
}
@JvmStatic
@Singleton
@Provides
fun getClient(connectivityInterceptorImpl: ConnectivityInterceptorImpl): ApiService {
val requestInterceptor = Interceptor { chain ->
val url = chain.request()
.url()
.newBuilder()
.addQueryParameter("api", KEY)
.build()
val request =
chain
.request()
.newBuilder()
.url(url)
.build()
return@Interceptor chain.proceed(request)
}
val okHttpClient = OkHttpClient
.Builder()
.addInterceptor(connectivityInterceptorImpl) // here it is
.addInterceptor(requestInterceptor)
.connectTimeout(60, TimeUnit.SECONDS)
.build()
return Retrofit.Builder()
.client(okHttpClient)
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ApiService::class.java)
}
}
}
枚举类
处理网络状态
enum class Status {
RUNNING,
SUCCESS,
FAILED
}
class NetworkState(val status: Status, val msg: String) {
companion object {
val LOADED: NetworkState = NetworkState(Status.SUCCESS,"Success")
val LOADING: NetworkState = NetworkState(Status.RUNNING,"Running")
val ERROR: NetworkState = NetworkState(Status.FAILED,"Failed")
}
}
存储库
在存储库中执行此操作:
如果您使用的是DataSource层,则可以在dataSource类中进行操作
private val _networkState = MutableLiveData<NetworkState>()
val returnNetworkState: LiveData<NetworkState>
get() = _networkState
fun networkData(){
CoroutineScope(IO).launch {
_networkState.postValue(NetworkState.LOADING)
try {
//Asynchronous Operation
_networkState.postValue(NetworkState.LOADED)
} catch (e: NoConnectivityException) { // custom exception class
Log.d(TAG, "No Internet Is Available")
_networkState.postValue(NetworkState.ERROR)
}
}
}
在活动/片段内部,通过 LiveData 相应地更新您的UI。
myViewModel.returnNetworkState.observe(this, Observer {
//textView or anything
})
全部完成。