2012-07-05 159 views
2

我正在创建排队的上传管理器。通过this回答我之前问题的指导,我将使用服务来上传这些图片。建议我使用数据库来跟踪成功上传的文件和待处理文件。在活动和服务之间共享数据库

我最初的研究让我相信我会创建一个绑定服务,所以一旦照片上传,我就可以更新我的UI,以及一个已启动的服务,因此它可以独立于我的活动运行创造它。看来我还需要通过应用程序清单中的process=":something"指令在自己的过程中启动它。

我的问题是,在N个活动客户端和上传服务器之间共享SQLite(除非有更好的方式)数据库的最佳方式是什么?

我想象它的工作就是这样,在伪代码:

// in an app 
writeRecordToDb(. . .); 

// start service 
if(service doesn't exist) 
{ 
    // start service, and bind 
} 

// in the service: 
if(shared db has another row) 
{ 
    doDownload(. . .); 

    if(download worked) 
    { 
    notifyActivity(); 

    if(db has another row) 
     doDownload(. . .); 
    } 
    else 
    { 
    retryDownload(. . .); 
    } 
} 

这是正确的方式去吗?我再次试图绕过有多个活动实例请求照片上传的问题,而这些问题几乎不存在任何蜂窝信号。我刚刚阅读了服务和绑定服务文档,我感觉很好,但并不好。

+0

除了已发布的答案之外,我从您提到的问题中看出,排队机制中的一个决定性因素是网络连接性。我使用'BroadcastReceiver'来监听连接的变化,并将它与'IntentService'耦合。我的'活动'发送网络请求到'IntentService',如果没有连接,它将请求添加到队列并终止。每当'BroadcastReceiver'接收到一个网络'connected''Intent',它就会启动IntentService,然后处理之前排队的任何东西。 – Squonk 2012-07-05 21:47:54

回答

4

我最初的研究使我相信,我会想建立一个绑定的服务

我不会。

所以一旦照片上传

你不需要使用结合模式来更新UI我可以更新我的UI。您可以:

  • 发送使用LocalBroadcastManager该活动回升,或
  • 调用由活动在Intent额外提供上startActivity()一个PendingIntent本地广播,或
  • 给广场的Otto event bus一试(长相有趣的,但我没有使用它)

以及一个启动的服务,因此它可以独立运行我的活动创建它的

这就是为什么你不应该结合烦心,因为你并不需要这一点,但你需要启动服务。

我的问题是,N活动客户端和上传器服务之间共享SQLite(除非有更好的方式)数据库的最佳方式是什么?

选项#1:保持你SQLiteOpenHelper在静态数据成员

选项#2:使用ContentProvider来包裹你的数据库

这是正确的方式去吗?

将数据库用作组件之间的通信通道类似于使用由双翼飞机拖曳的横幅相互通信的两个隔壁邻居。是的,它的工作原理。但是,它很慢,而且很昂贵。

(也,当你需要一个从未有双翼飞机,但我离题...)

如果您希望使用一个数据库作为后备存储未处理的下载,万一有一些中断(如,用户会关闭设备),并且您希望稍后拿起这些下载,那很好。但是,该服务将通过您通过startService()发送给它的命令知道要下载什么内容。

3

CommonsWare基本涵盖了你需要的一切......但这里有一些代码说明两种选择,以防万一出现混淆。

  1. 将您的SQLiteOpenHelper保存在静态数据成员中。

    public class DatabaseHelper extends SQLiteOpenHelper { 
        private static DatabaseHelper mInstance = null; 
    
        private static final String DATABASE_NAME = "databaseName"; 
        private static final String DATABASE_TABLE = "tableName"; 
        private static final int DATABASE_VERSION = 1; 
    
        private Context mCxt; 
    
        public static DatabaseHelper getInstance(Context ctx) { 
         /** 
         * use the application context as suggested by CommonsWare. 
         * this will ensure that you dont accidentally leak an Activitys 
         * context (see this article for more information: 
         * http://developer.android.com/resources/articles/avoiding-memory-leaks.html) 
         */ 
         if (mInstance == null) { 
          mInstance = new DatabaseHelper(ctx.getApplicationContext()); 
         } 
         return mInstance; 
        } 
    
        /** 
        * constructor should be private to prevent direct instantiation. 
        * make call to static factory method "getInstance()" instead. 
        */ 
        private DatabaseHelper(Context ctx) { 
         super(context, DATABASE_NAME, null, DATABASE_VERSION); 
         this.mCtx = ctx; 
        } 
    } 
    

    然后在你Service/Activity,保持对它的引用您的DatabaseHelper并调用它getInstance()

  2. 将数据库包装在ContentProvider中。如果你已经有了一个实现,那么你可以简单地使用

    mContext.getContentResolver().query(...); 
    

    这工作,因为ActivityService都扩展Context(持有到ContentResolver参考)。