我有一个执行数据库或网络请求的内容提供商。如果没有网络,则引发IOException,我想再做一次请求(这次在数据库上)。
我的代码看起来像
/**
* Content provider
*/
//...
public Cursor query (Uri uri /*,...*/) {
switch(uriMatcher.match(uri)) {
case NETWORK:
JSONObject json;
try {
json = new HttpTask().getItems(); // If no network throws IoException
} catch (IOException e) {
//Do something
}
return new Cursor(/* ... */);
break;
case DATABASE:
//Access database
return new Cursor(/* ... */);
break;
}
}
//...
我应该:
HttpTask
中的例外,以便json
“只是”为空编辑1
或者我应该在使用之前检查网络状态:
ConnectivityManager connectivityManager = (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager != null) {
NetworkInfo ni = connectivityManager.getActiveNetworkInfo();
if (ni.getState() != NetworkInfo.State.CONNECTED) {
// record the fact that there is not connection
isConnected = false;
}
}
编辑2 以下是使用自定义例外和自定义加载器的方法
NoNetworkException.java
public class NoNetworkException extends RuntimeException {
public NoNetworkException(String s) {
super(s);
}
}
NoNetworkSafeCursorLoader.java
public class NoNetworkSafeCursorLoader extends CursorLoader {
private NoNetworkException exception;
public NoNetworkSafeCursorLoader(Context context, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
super(context, uri, projection, selection, selectionArgs, sortOrder);
}
@Override
public Cursor loadInBackground() {
try {
return super.loadInBackground();
} catch(NoNetworkException exception) {
this.exception = exception;
}
return null;
}
public NoNetworkException getException() {
return exception;
}
}
现在在内容提供商中,您需要抛出NoNetworkException
//...
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) throws NoNetworkException {
//...
}
//...
并且在回调中你必须检查是否抛出了异常
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) throws NoNetworkException {
NoNetworkSafeCursorLoader l = (NoNetworkSafeCursorLoader) loader;
if(l.getException() != null) {
//No network, do somethings
}
else {
//Network ok, do otherthings
}
}
答案 0 :(得分:1)
您首先应该检查网络状态。然后,如果网络请求失败,请在catch
- 块
public Cursor query (Uri uri /*,...*/) {
Cursor cursor;
switch(uriMatcher.match(uri)) {
case NETWORK:
JSONObject json;
try {
json = new HttpTask().getItems(); // If no network throws IoException
cursor = new Cursor(/* convert json */)
} catch (IOException e) {
cursor = //access the database
}
break;
case DATABASE:
//Access database
cursor = new Cursor(/* ... */);
break;
}
return cursor;
}
另外,您应该看一下Sync Adapters这是谷歌说你应该这样做的方式。根据您的使用情况,它可能是一个很好的帮助,因为同步适配器已经处理网络检查和其他事情,以最大限度地延长电池寿命。
答案 1 :(得分:1)
在这种情况下,你可以做的事情很少,
是的,@ leoderprofi说,您必须检查网络是否可用于您想要的HTTP任务。
而不是在抛出异常后使用Try Catch进行管理。您可以做的是在此之前检查对象可用性。比如,在解析之前检查JSON是否为null,在获取游标之后还检查它是否为null,如果不是null,它实际上是否有任何数据init,它最有可能在游标中得到异常对象存在但它没有任何数据,当你从中获取数据时给你例外。
是的,你可以创建一个自定义加载器并处理并在那里抛出异常,你也可以做的就是使用接口管理它来创建成功和错误回调。
希望它有所帮助。 感谢。
答案 2 :(得分:1)
正确的解决方案......封装您的网络功能,如果网络不可用则故障转移到数据库,无需第二次查询调用。
我不会创建一个自定义加载器和异常,除非你的客户端真的想知道网络尝试失败了,但如果它只是用db请求跟进它,那么为什么要打扰通知任何人,但这取决于你的用例。
不知道你的实际要求;删除NETWORK和DATABASE内容URI并使用一个MY_DATA更清晰。您的客户是否真的知道或关心它是否要求/或?
public Cursor query (Uri uri /*,...*/) {
switch(uriMatcher.match(uri)) {
case NETWORK:
// check network
if ( isNetworkAvailable(context) ) {
JSONObject json;
try {
json = new HttpTask().getItems(); // If no network throws IoException
return new Cursor(/* ... */);
} catch (IOException e) {
// Log a warning
}
}
// delete this break;
// failover to DB
case DATABASE:
//Access database
return new Cursor(/* ... */);
break;
}
}
private boolean isNetworkAvailable(Context ctx) {
boolean isConnected = false;
ConnectivityManager connectivityManager = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager != null)
NetworkInfo ni = connectivityManager.getActiveNetworkInfo();
isConnected = ni.getState() == NetworkInfo.State.CONNECTED;
}
return isConnected;
}
您甚至可以使用公共静态布尔值isNetworkAvailable(...),以获得可在其他地方使用的简单实用方法。