0

でコードを実行するスティッキー サービス (START_STICKYから戻る) がありますが、開始、バインド、停止、バインド解除の方法とタイミングに問題があります。親アクティビティが生きている間だけサービスが必要です。アプリが閉じられたときにバックグラウンドでぶらぶらしたくありませんが、方向の変更に耐えるためにサービスが必要です。現在、アクティブなアクティビティの全期間にわたってサービスをアクティブにする必要はないため、 で主な作業が完了した後に stopSelf() を呼び出し、必要に応じてを再度開始します。場合によっては、サービスが実行している作業を中断し、キャンセルする必要がありますonStartCommandAsyncTaskAsyncTaskServiceServiceAsyncTask別のデータでやり直します。問題は、私が何をしようとも、考えられるさまざまなシナリオのすべてで確実に理解できないように見えることです。誰かが目を通して、私が間違っていることを教えてもらえますか?

Serviceは:

public class ChordCalculatorService extends Service {

    private final IBinder mBinder = new LocalBinder();
    private AsyncTask<SearchData, SearchStatusData, List<Item>> currentTask;

    @Override
    public void onCreate() {}

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // We want this service to continue running until it is explicitly
        // stopped, so return sticky.
        return START_STICKY;
    }

    /**
     * Class for clients to access. Because we know this service always runs in
     * the same process as its clients, we don't need to deal with IPC.
     */
    public class LocalBinder extends Binder {
        public ChordCalculatorService getService() {
            return ChordCalculatorService.this;
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    public SearchData getSearchData() {
        return searchData;
    }        

    public void startWork() {
        if (currentTask != null && currentTask.getStatus() == Status.RUNNING) {
            currentTask.cancel(true);
        }
        if(searchData != null) {
            Worker task = new Worker();
            currentTask = task.execute(new SearchData[] { searchData });
        } else {
            Message msg = handler.obtainMessage(ERROR, "No search data set");
            handler.sendMessage(msg);
        }
    }


    class Worker extends AsyncTask<SearchData, SearchStatusData, List<Item>> {
        // ... code ...

        @Override
        protected void onPostExecute(List<Item> result) {
            Message msg = handler.obtainMessage(COMPLETE, new StatusData(Status.STATUS_FINISHED, result));
            handler.sendMessage(msg);
            stopSelf();
        }
    }
}

現在Service、カスタムViewが作成されたときに開始されています。

public class MyCustomView extends BasicFretBoardView  {

    private ServiceConnection conn;
    private MyService myService;
    private boolean isServiceStarted;
    private boolean isServiceBound;

    public MyCustomView(Context context, AttributeSet attr) {
        super(context, attr);
        startService();
    }

    public void startService() {
        Intent serviceIntent = new Intent(getContext(), MyService.class);
        conn = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                myService = ((LocalBinder) service).getService();
                myService.registerHandler(serviceHandler);
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                myService = null;
            }
        };

        // Explicitly start the service. Don't use BIND_AUTO_CREATE, since it
        // causes an implicit service stop when the last binder is removed.

        getContext().startService(serviceIntent);
        getContext().bindService(serviceIntent, conn, 0);
        isServiceStarted = true;
        isServiceBound = true;
    }

    public void stopService() {
        if (isServiceStarted) {
            Intent serviceIntent = new Intent(getContext(), MyService.class);
            getContext().stopService(serviceIntent);
            isServiceStarted = false;
        }
        unBindService();
    }


    public void unBindService() {
        if(isServiceBound) {
            getContext().unbindService(conn);
            isServiceBound = false;
        }
    }

    // gets called based on some user interaction
    private void startServiceWork() {
        if(!isServiceStarted) {
            startService();
        } else {
            myService.cancelCalcalation();
        }
        myService.setData(data);
        myService.startWork();
    } 
}

サービスの停止は で処理されますActivity

public class CustomChordActivity extends Activity {

    // ... code ...

    @Override
    public void onBackPressed() {
        super.onBackPressed();
    }

    @Override
    protected void onPause() {
        if(isFinishing()) {
            chordsView.stopService();
        }
        super.onPause();
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        chordsView.unBindService();
        super.onDestroy();
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
    }
}
4

1 に答える 1

0

タスクをオンデマンドで実行したいようですが、おそらく IntentService がより適切なオプションになるでしょう。作業を行う必要がある場合 (startServiceWork())、サービスを開始するだけで、AsyncTask が開始されます。タスクが終了すると、サービスは終了します。

ここで、向きの変更に関しては、インテント フィルターが「android.intent.action.CONFIGURATION_CHANGED」であるブロードキャスト レシーバーを実装する必要があります。(向きが変わったときにサービスを機能させたいと思います)アクティビティ/メインUIスレッド内にブロードキャストレシーバーを配置します。これにより、事実上、ブロードキャスト レシーバーのホスティング プロセスがメイン アプリケーション プロセスになり、ブロードキャスト レシーバー内からサービスをより安全に開始できるようになります。

于 2011-09-16T18:23:41.393 に答える