2013-04-08 37 views
2

我有一个ContentProvider实现从基础SQLite数据库提供的地理位置列表。从互联网资源更新ContentProvider的基础SQLite数据库

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

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

我开始实现它在我ContentProvider称为updateSiteList公共职能,但我不知道如何实际调用它(ContentProvider的通常是通过CursorLoader间接acessed)!

我对于如何进步有点困惑!

任何人都可以指向正确的方向吗?

谢谢!

回答

2

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

1)自定义同步适配器。

2)意向服务。

对于选项1你的Android系统处理网络连接问题的利益,是由Android开发

对于选项2你当数据被下载了更多的控制推荐的方法可能会或可能不会成为用户或Android系统的最佳时机。

无论哪种方式,解决方案是相同的。在某个时间点,您将在后台服务中向网址发送HTTP请求。当您的请求完成时,您需要检查响应的状态,并在适当的情况下,您将调用内容提供程序以相应地插入或更新数据。无论你采取这一部分的方法将是相同的。

为您进一步阅读。 https://sites.google.com/site/andsamples/concept-of-syncadapter-androidcontentabstractthreadedsyncadapter

请务必看,谷歌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; 
    } 

这不是一个复制和粘贴的解决方案。仅仅是一个例子从我的一个应用程序中剥离出来,你应该看看每一行代码,并且非常小心地理解正在发生的事情。

+0

非常感谢您的详细解答!对同步适配器进行编码看起来有点复杂 - 尤其是帐户方面。我将用IntentService方法来尝试它。再次感谢! – ccbunney 2013-04-09 19:53:17