6

パーセンテージを更新し続けるアクティビティがあり、AsyncTask内で実行されるデータベース更新操作があります。

doInBackground()内で、データベースを更新するコントローラーを呼び出し、アクティビティのパーセンテージを更新し続けますが、ホームボタンまたは戻るボタンを押すと、操作がキャンセルされます。あなたは私に何をするように提案しますか?

バックグラウンドで実行されるようにdoInBackground()内でサービスを開始しようとしましたが、機能していないようです。

私のコードは次のようになります:

public class UpdateDatabaseAsyncTask extends AsyncTask<Void, Integer, Integer>
{   
    @Override
    public void onPreExecute()
    {
        mCustomProgressBar.startAnimation();
    }

    @Override
    public Integer doInBackground(Void... params)
    {
        return mController.updateDatabase();
    }

    @Override
    public void onPostExecute(Integer result)
    {
        mCustomProgressBar.stopAnimation();
        // finish the activity
    }

    @Override
    public void onProgressUpdate(Integer... value)
    {
        updatePercentageValue(value[0]);
    }

    public void callPublishProgress(Integer value)
    {
        publishProgress(value);
    }
}

そして、コントローラー内でcallPublishProgress(value)、現在のパーセンテージ値を渡すメソッドを呼び出すのでpublishProgress(value)、UIに表示されます。

デバッグしていて、ホーム/戻るボタンを押したところ、ワーカースレッドの実行が停止しました。


私が試したもう1つの解決策は、ユーザーがホーム/戻るボタンを押すかどうかに関係なく、バックグラウンドで実行するサービスを開始することでした。そのため、サービスは、作業を行うコントローラーメソッドを呼び出し、callPublishProgress(value)とにかくUIのパーセンテージ値を更新します。

しかし、何が起こっていたのかというと、コードdoInBackground() はサービスに到達して開始しますが、onPostExecute()すぐに実行され、サービスが終了するのを待たなかっただけです(もちろん!)。だからそれは与えるNullPointerException。サービスにフラグを設定して内部doInBackground()でループを作成することを考えたので、サービスが終了していない間(IntentServiceを使用していた)はこのループを終了しますが、とにかく機能しませんでした。

タイマーも使うことを考えました。でもわかりません。

スレッドなどに関するドキュメントの記事を読んでいました。それはAsyncTask、私がやろうとしていたのと同じように、を使用することを提案しています。また、について話しrunOnUiThread(Runnable)ます。

とにかく私が必要なのはバックグラウンドで(おそらくIntentServiceを使用して)操作を行うことなので、ユーザーがホームボタンを押しても実行は継続されますが、UIのパーセンテージを更新する必要があり、ユーザーが画面に戻ると、画面で更新された現在のパーセンテージ値が表示されます。

私の場合の最善の解決策は何ですか?

ありがとう。

4

3 に答える 3

5
public class MyServce extends Service{
public static final String BROADCAST_ACTION = "com.myapp";
Intent intent;
private final Handler handler = new Handler();

@Override
public void onCreate()
{
    super.onCreate();
    intent = new Intent(BROADCAST_ACTION);
}

 @Override
    public void onStart(Intent intent, int startId) {
        handler.removeCallbacks(sendUpdatesToUI);
        handler.postDelayed(sendUpdatesToUI, 1000); // 1 second

    }
   private Runnable sendUpdatesToUI = new Runnable() {
        public void run() {
            DoYourWorking();        
            handler.postDelayed(this, 1000); // 1 seconds
        }

        private void DoYourWorking() {
        ........
                    ........
                     intent.putExtra("key", progress);
             sendBroadcast(intent);

        }
    };   

@Override
public IBinder onBind(Intent intent) {
    // TODO Auto-generated method stub
    return null;
}
@Override
public void onDestroy() {   
    super.onDestroy();
    handler.removeCallbacks(sendUpdatesToUI);       

}

アクティビティ レジスタでサービスにブロードキャストするようになりました

private BroadcastReceiver brodcast = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
                 //intent.getWhatever
        // update your progress
        //progressbar.setProgress 
    }

ブロードキャストを登録する

 registerReceiver(brodcast, new IntentFilter(MyService.BROADCAST_ACTION));
于 2012-04-27T17:32:45.017 に答える
1

IntentService (独自のスレッド上のサービス) とHandlerを使用して、データをアクティビティに戻します。

于 2012-04-27T17:30:53.947 に答える
1

これは私にとってはうまくいきました。シングルトンで値をフェッチしてオブジェクトを更新するだけのスレッドでバックグラウンド サービスを開始しました。

ビュー コントローラーでは、シングルトンでオブジェクトからデータをフェッチしてビューを更新し続けるタイマーを開始します。

質問のテキスト全体を理解するのに少し問題があったため、これを試したかどうかわかりません. しかし、これがうまくいきました。また、サービスを開始したのはSTART_STICKY

于 2012-04-27T17:24:59.710 に答える