Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/222.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何处理来自ContentProvider的异常?_Android_Android Contentprovider - Fatal编程技术网

Android 如何处理来自ContentProvider的异常?

Android 如何处理来自ContentProvider的异常?,android,android-contentprovider,Android,Android Contentprovider,我有一个执行数据库或网络请求的内容提供商。如果没有网络,则会引发IOException,我希望执行另一个请求(这次是在数据库上) 我的代码看起来像 /** * Content provider */ //... public Cursor query (Uri uri /*,...*/) { switch(uriMatcher.match(uri)) { case NETWORK: JSONObject json; tr

我有一个执行数据库或网络请求的内容提供商。如果没有网络,则会引发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;
    }
}
//...
我应该:

  • 是否仅在contentProvider中处理异常,并在发生错误时直接移动到数据库案例
  • HttpTask
    中处理异常,以便
    json
    将“刚好”为空
  • 创建这样的自定义游标加载程序和自定义RuntimeException?如果是这样,在内容提供程序中,我将能够抛出异常并在游标加载程序中捕获它
  • 编辑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
        }
    }
    
    @覆盖
    public void onLoadFinished(加载器、游标数据)引发非TworkException{
    NoNetworkSafeCursorLoader l=(NoNetworkSafeCursorLoader)装载机;
    如果(l.getException()!=null){
    //没有网络,做点什么吧
    }
    否则{
    //网络好,做其他事情
    }
    }
    
    您必须首先检查网络状态。然后,如果网络请求失败,则在
    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;
    }
    

    此外,你还应该看看谷歌说你应该用什么方式来解决这个问题。根据您的使用情况,这可能是一个很大的帮助,因为同步适配器已经可以处理网络检查和其他事情,以最大限度地延长电池寿命。

    在这种情况下,您可以注意的事情很少

  • 是的,正如@leoderprofi所说,您必须检查网络是否可用于您想要的HTTP任务

  • 而不是在抛出异常后使用Try-Catch进行管理。在此之前,您可以检查对象的可用性。比如,在解析JSON之前检查它是否为null,在获取光标之后检查它是否为null,如果不是null,那么它是否实际具有任何数据init,游标对象存在,但其中并没有任何数据,当您从中获取数据时,它很可能在游标中出现异常

  • 是的,您可以创建一个自定义加载程序并在那里处理和抛出异常,您还可以使用接口为该接口创建一个成功和错误回调来管理它

  • 希望能有帮助。
    谢谢。

    一个合适的解决方案…封装您的网络功能,如果网络不可用,故障切换到db,无需第二次查询调用

    我不会创建自定义加载程序和异常,除非您的客户机真的想知道网络尝试失败,但是如果它只是用db请求来跟踪它,那么为什么还要麻烦通知任何人,但这取决于您的用例

    不知道你的实际需求;去掉网络和数据库内容URI,只使用一个MY_数据,会更干净。您的客户是否真的知道或关心其是否要求提供任何一种服务

    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(…)成为一种简单实用的方法,您可以在其他地方使用。

    谢谢您的回答。我将很快研究
    SyncAdapter
    。因此,如果我想向用户返回一条消息(基本上是“无网络,做其他事情”),创建一个自定义异常听起来很合理。是的,我认为如果你想创建并抛出自定义运行时异常也可以。