2

我已经实现了ContentProvider一个从底层 SQLite 数据库提供地理位置列表的服务。

这些位置实际上是模型的输出,并以简单的 JSON 字符串形式在线提供;我不想在每次启动应用程序时都继续下载它们,所以我想将它们本地存储在数据库中并以预定义的时间间隔更新它们(例如每天一次)。

我的问题是,我应该在哪里实现下载和解析代码?它应该成为我ContentProvider实施的一部分吗?还是SQLiteOpenHelper实施的一部分?

我开始将它实现为updateSiteList在 my中调用的公共函数ContentProvider,但我不知道如何实际调用它(ContentProvider 通常通过 间接访问CursorLoader)!

我对如何进步感到有点困惑!

谁能指出我正确的方向?

谢谢!

4

1 回答 1

2

有几种方法可以实现这一目标。我使用的两种最常见的方法是:-

1)自定义同步适配器。

2) 意向服务。

使用选项 1,您可以获得 Android 系统处理网络连接问题的好处,并且是 android 开发人员推荐的方法

使用选项 2,您可以更好地控制何时下载数据,这可能是也可能不是用户或 Android 系统的最佳时间。

无论哪种方式,解决方案都是相同的。在某个时间点,您将在后台服务中向 url 发出 HTTP get 请求。当您的请求完成时,您将需要检查响应的状态,如果合适,您将致电内容提供商以相应地插入或更新您的数据。无论您采取哪种方法,这部分都是一样的。

一些进一步的阅读给你。 https://sites.google.com/site/andsamples/concept-of-syncadapter-androidcontentabstractthreadedsyncadapter

请务必观看 Google I/O 视频

无论您采用哪种方法,下载 json 并插入到您的内容提供程序的代码在从您的同步适配器或从您的应用程序中的某个位置调用的 IntentService 中可能看起来像这样(如果不使用同步适配器)。

public class ServiceInitialiseData extends IntentService {
    static final String TAG = "ServiceSyncData";
    //ACTION should include application package convention, just to show that this can
    //be any string
    public static final String SYNC_COMPLETED_ACTION="com.pjmobile.games.fantasyf1.SyncCompleted";

    public ServiceInitialiseData() {
        super("InitialiseDataService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        String sJson;
        try {
            sJson = downloadFromServer("Some parsed url");
            int i, x;
            boolean res = false;
            List <ContentValues> bulkValues = new ArrayList <ContentValues>();
            JSONArray entries;
            try {
                entries = new JSONArray(sJson);
                ContentValues cvEntity = null;
                JSONObject entity;
                x = entries.length();
                for (i=0;i<x;i++){
                    entity = entries.getJSONObject(i).getJSONObject("some_json_key");
                    bulkValues.add(cvEntity);
                }
            }
            int qCount = getContentResolver().bulkInsert(uri,
            (ContentValues[])bulkValues.toArray(new
                    ContentValues[bulkValues.size()]));

            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    private String downloadFromServer(String url) throws ClientProtocolException, IOException {
        HttpResponse sJson = getJSONEntityFromURL(this, url);
        return EntityUtils.toString(sJson.getEntity());
    }

    private static HttpResponse getJSONEntityFromURL(Context context, String url) throws ClientProtocolException, IOException {
        HttpClient httpclient = new DefaultHttpClient();
        HttpGet httpget = new HttpGet(url);
        httpget.addHeader("Accept", "application/json");
        httpget.addHeader("Content-Type", "application/json; charset=UTF-8");
        HttpResponse response;

        response = httpclient.execute(httpget);
        return response;
    }

要使上述方法正常工作,您必须对内容提供者的批量插入方法进行 ode,这可能看起来像这样

    @Override
    public int bulkInsert(Uri uri, ContentValues[] values) {
        final SQLiteDatabase db = mDB.getWritableDatabase();
        final int match = sURIMatcher.match(uri);
        int numInserted= 0;
//        Util.log_debug_message("@@@@ URI MATCH - " + match);
        switch(match){
            case TEAMS:
                numInserted = insertTeams(db, values);
                break;
            default:
                throw new UnsupportedOperationException("unsupported uri: " + uri);
        }
        getContext().getContentResolver().notifyChange(uri, null, false);
        return numInserted;
    }

    private int insertTeams(SQLiteDatabase db, ContentValues[] values) {
        int numInserted = 0;
        db.beginTransaction();
        try {
        //standard SQL insert statement, that can be reused
            SQLiteStatement insert = 
                db.compileStatement(INSERT_OR_REPLACE_STRING + TeamModel.TEAM_TABLE_NAME
                        + "(" + TeamModel.COL_SERVER_ID
                        + "," + TeamModel.COL_BONUS_RACE_ID
                        + "," + TeamModel.COL_POINTS
                        + "," + TeamModel.COL_POSITION
                        + "," + TeamModel.COL_TEAM_NAME + ")"
                        +" values " + "(?,?,?,?,?)");

            for (ContentValues value : values){
    //bind the 1-indexed ?'s to the values specified
                insert.bindString(1, value.getAsString(TeamModel.COL_SERVER_ID));
                insert.bindString(2, value.getAsString(TeamModel.COL_BONUS_RACE_ID));
                insert.bindString(3, value.getAsString(TeamModel.COL_POINTS));
                insert.bindString(4, value.getAsString(TeamModel.COL_POSITION));
                insert.bindString(5, value.getAsString(TeamModel.COL_TEAM_NAME));
                insert.execute();
            }
            db.setTransactionSuccessful();
            numInserted = values.length;
        } finally {
            db.endTransaction();
            db.close();
        }
        return numInserted;
    }

这不是复制和粘贴解决方案。只是从我的一个应用程序中删除的一个示例,您应该查看每一行代码并非常小心地了解发生了什么。

于 2013-04-09T12:11:44.873 回答