2

私はContentProvidersqlite データベースからデータをフェッチし、 経由でロードするを持っていますLoader。サーバーからデータをダウンロードしてで更新するServiceを実行するによって更新されます。明確であることを願っていますが、念のため:AsyncTaskContentProvider

  • ListFragmentContentProvider経由Loaderでデータを取得します。

  • ContentProviderで更新されServiceます。

ここで、アプリを初めて起動したときにローカルの sqlite データベースが空の場合、Service. 私はむしろProgressBarこの瞬間にショーをしたいと思います(バーではなく、無限の糸車)。しかし、ProgressBarデータベースからの結果がない場合に a を表示すると、外部データベースにレコードがないこの特定のケースでサーバーからデータをフェッチした後でもそこに表示されます (私の場合は非常に頻繁に発生します)。そう:

  • データが初めてダウンロードされるとき、空でない結果が得られるまで、または仕事が完了するまでService ProgressBar を表示したいと思います。ContentProviderService

  • ContentProvider何も返されず、ジョブ が終了したService(そして空の結果がフェッチされた)場合、アプリに「結果が見つかりません」と表示させたいと思います。

私の問題はおそらくListFragmentServiceがまだ実行中であること、または ts ジョブが終了したことを に通知する方法です。Fragmentつまり、内部の呼び出しへの参照を保存するべきではありませんService。の考えに反しContentProvidersますね。では、どうやって?

注: ここでコードのどのフラグメントが役立つかはよくわかりません。そのため、特定のフラグメントを確認する必要があると思われる場合は、コメントで教えてください。ありがとう!

4

2 に答える 2

1

Fragment/Activityと a の間の通信方法にはさまざまな手法がありますService

そのうちの 1 つは、ResultReceiverを使用して、 IntentServiceに追加で送信することIntentです。

カスタム レシーバーServiceResultReceiver拡張を作成しますResultReceiver

public class ServiceResultReceiver extends ResultReceiver {

    private Receiver mReceiver;

    public ServiceResultReceiver(Handler handler) {
        super(handler);
    }

    public void setReceiver(Receiver receiver) {
        mReceiver = receiver;
    }

    public interface Receiver {
        public void onReceiveResult(int resultCode, Bundle resultData);
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        if (mReceiver != null) {
            mReceiver.onReceiveResult(resultCode, resultData);
        }
    }
}

Fragment実装ServiceResultReceiver.Receiverインターフェイスを作成します。レシーバーを作成し、それを に初期化しますFragment。受信者をサービスに渡し、サービス中は受信者をインテントから取得し、receiver.send()何かを受信者に送り返すように呼び出します。

public class MyFragment extends ListFragment implements ServiceResultReceiver.Receiver {
    private ServiceResultReceiver mReceiver;
    ....

    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        mReceiver = new ServiceResultReceiver(new Handler());
        mReceiver.setReceiver(this);
    }

    public void startMyService() {
        final Intent intent = new Intent(getActivity(), MyService.class);
        intent.putExtra("receiver", mReceiver);
        getActivity().startService(intent);
    }

    @Override
    public void onReceiveResult(int resultCode, Bundle resultData) {
        // service finished
    }
}

public class MyService extends IntentService {
    ...
    @Override
    protected void onHandleIntent(Intent intent) {
        // download data and update database
        ....
        final ResultReceiver receiver = intent.getParcelableExtra("receiver");
        if (receiver != null) {
            receiver.send(0, null);
        }
    }
}
于 2012-07-24T21:51:25.033 に答える
1

実際の進行状況を UI にポストすることにはあまり関心がないので、これを実装する最も簡単な方法は、カスタム ブロードキャストのペアを使用し、実行状態も表示する静的ブール値を使用することです。

基本的に、サービスは、関心のあるアプリケーションの任意のコンポーネントに、ダウンロードの開始時と終了時に通知できます。したがって、次の 2 つのカスタム アクション文字列を定義できます。

public static final String ACTION_DOWNLOADSTART = "com.mypackage.intent.ACTION_DOWNLOADSTART";
public static final String ACTION_DOWNLOADCOMPLETE = "com.mypackage.intent.ACTION_DOWNLOADCOMPLETE";

次に、コード内の適切なポイントでサービスにそれらをブロードキャストさせます。

Intent start = new Intent(ACTION_DOWNLOADSTART);
sendBroadcast(start);

//...Service does its work

Intent finish = new Intent(ACTION_DOWNLOADCOMPLETE);
sendBroadcast(finish);

これらのコールバックは、アプリケーション内の任意の場所で を使用して登録し、BroadcastReceiverそれに応じて処理できます (つまり、 のステータスを確認し、ContentProvider必要に応じて進行状況を表示/非表示にします)。

Service別の一般的な方法として、特定の時点で が実行されているかどうかを確認できるようにする場合は、がアクティブなprivate static booleanときに切り替えられるメンバー(おそらく/の間で、おそらく他の場所) と のようなアクセサー メソッドを含めるだけです。次に、アプリケーションは、そのメソッドを呼び出すだけで、 が実行されているかどうかをいつでも確認できます。ServiceonCreate()onDestroy()isRunning()Service

于 2012-07-24T22:11:44.197 に答える