2

キューアップロードマネージャーを作成しています。前の質問のガイダンスに対するこの回答で、サービスを使用してこれらの画像をアップロードしますデータベースを使用して、正常にアップロードされたファイルと保留中のファイルを追跡することをお勧めしました。

私の最初の調査では、バインドされたサービスを作成したいと思うようになりました。これにより、写真がアップロードされたら 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( . . . );
  }
}

これは正しい方法ですか?セルラー信号がほとんどまたはまったくない場合に、複数のアクティビティ インスタンスが写真のアップロードを要求するという問題を回避しようとしています。Service と Bound Service のドキュメントを読み終えたところです。気分は良いですが、あまり良くありません。

4

2 に答える 2

4

My initial research leads me to believe that I'll want to create a Bound Service

I wouldn't.

so I can update my UI once the photos have uploaded

You do not need to use the binding pattern to update the UI. You can:

  • send a local broadcast using LocalBroadcastManager that the activity picks up, or
  • invoke a PendingIntent supplied in an Intent extra on startActivity() by the activity, or
  • give Square's Otto event bus a try (looks interesting, but I haven't used it yet)
  • etc.

as well as a Started Service, so it can run independent of my Activities that create it

Which is why you should not bother with binding, as you do not need that, but you do need to start the service.

My question is, what would the best way of sharing an SQLite (unless there is a better way) database amongst the N activity clients and the uploader service?

Option #1: Keep your SQLiteOpenHelper in a static data member

Option #2: Use a ContentProvider wrapper around your database

Is this the correct way to go about this?

Using a database as a communications channel between components is akin to two next-door neighbors communicating with each other using a banner towed by a biplane. Yes, it works. However, it is slow and expensive.

(also, there's never a biplane when you need one, but I digress...)

If you wish to use a database as a backing store for pending downloads, in case there is some interruption (e.g., user powers down the device) and you wish to pick up those downloads later on, that's fine. However, the service will know what to download by the command you send to it via startService().

于 2012-07-05T21:27:12.683 に答える
3

CommonsWare は基本的に必要なものすべてをカバーしています... しかし、混乱がある場合に備えて、2 つのオプションを示すコードをいくつか示します。

  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)。

于 2012-07-05T21:39:57.410 に答える