11

Async タスクが正しく動作しない場合があることに気付きました。実際にはdoInBackground() メソッドが呼び出されません。これは主に、そのアクティビティのバックグラウンドでサービスが実行されている場合に発生します。たとえば、音楽がサービスを使用してバックグラウンドで実行される場合、Async タスクはバックグラウンドで XML を解析しません。これは、その doInBackground がその時点で機能せず、progress Dialog または progressBar が回転し続けるためです。

AsyncTask.THREAD_POOL_EXECUTORが次のような問題に役立ついくつかの記事を読みました。

if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
    new Test().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
    new Test().execute();
}

しかし、それは私の場合には役に立ちませんでした。上記の実装後に同じ問題が発生しました。

ここで、私が何をしているのかを理解するために、サンプル コードを少しだけ示します::

public class TestAct extends Activity {

    ImageButton play,forward,backward;  
    private ListView mList;
    // many more variables

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test_layout);

        //binding the service here
        // start service is called

        init();
    }

    private void init(){

        play=(ImageButton)findViewById(R.id.playBtn);
        forward=(ImageButton)findViewById(R.id.forward);
        backward=(ImageButton)findViewById(R.id.backward);  
        mList=(ListView)findViewById(R.id.list);

        new GetData().execute();

        play.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // calling the play() method of ServiceConnection here
            }
        });

            // adding header to Listview
            // other code and click listeners

    }

    class GetData extends AsyncTask<Void, Void, Void>{

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            // starting the progress Bar
            // initializing the Arraylist,Maps etc
        }

        @Override
        protected Void doInBackground(Void... params) {
            //parsing the XML here
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            // stop the ProgressBar 
            // Updating my UI here
                    // setting Adapter for ListView 
        }   
    }
}

これは通常は正常に機能しますが、サービスがバックグラウンドで実行されている場合 (つまり、バックグラウンドで音楽が再生されている場合) にハングします。

この非同期タスクの問題の背後にある正確な理由がわかりません。この場合、手動スレッドの実装は役立ちますか??

まあ、問題は「サービスはメインスレッドで実行されるため、実行するとAsyncTaskの実行がブロックされる」ためだと思います...したがって、バックグラウンドスレッドでサービスを実行できれば、それが役立つと思います. そのため、別のスレッドでサービスを実行するために IntentService を試しましたが、疑問です... IntentService が Service と同様に無期限に実行できるかどうか ... また、IntentService は AsyncTask を数回ブロックします。したがって、この種の問題に対する 100% 完璧な解決策とは思えません。

この問題を整理し、完全なシナリオを理解するのを手伝ってくれる人はいますか?

前もって感謝します。

4

7 に答える 7

3

場合によっては、サービスのライフサイクルを IntentService が提供するものよりも詳細に制御したい場合があります。そのような場合は、サービスでスレッドを作成し、その中でバックグラウンド コードを実行するだけです。実際には、より具体的には、ルーパーを含む HandlerThread を作成して、メイン スレッドとバックグラウンド スレッド間の通信 (メッセージ) に標準の android メソッドを使用できるようにします。

ここで回答済み

于 2013-02-22T10:50:50.850 に答える
1

ここに掲載されているすべての問題と回答をお読みください。私が間違っている場合は修正してください。あなたのシナリオは、xml を解析して曲のリストを取得していて、ユーザーがサービスで再生したい曲を選択したときに正しいですか?

シナリオが正しければ、はるかに簡単な方法で実装できます。

  1. アクティビティでは、onResume()メソッドは XML ファイルを解析して曲のリストを取得し、リスト ビューを更新します (ここではサービスに関連するものを開始しないでください)。
  2. ユーザーが曲をクリックすると、意図的に特定のキー/文字列がサービスに渡され、サービスが開始されます
  3. サービスのOnStartCommand()メソッドで識別子を取得し、通常のメディア API と同様に曲を開始します

それは実際にあなたのために仕事をします。

の問題について

if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
    new Test().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
    new Test().execute();
}

これは、AsyncTask異なるバージョンの Android での異なる動作のためのものです。コードを見ると、サービスを初期化しているアクティビティにあるため、サービスは何も実りのないバックグラウンドで実行されています。ユーザーが再生をクリックすると、ここで問題を引き起こしたサービスの再生機能が呼び出されます。

したがって、アクティビティからサービスの機能を呼び出すには、言及していないAIDLを正しくする必要があります。あなたがそう書いたなら、それは完璧なはずです。

ただし、ここでの推奨事項は、曲IDをサービスに渡し、サービスから再生する必要があり、アクティビティでサービスの関数を呼び出さないことです。

アクティビティの onResume でソング リストを更新する場合は、AIDL を記述してシナリオを実行する必要があります。

これが役立つことを願っています。

于 2013-02-22T11:19:52.210 に答える
1

Async タスクが正常に動作しない場合があることに気付きました。実際には doInBackground() メソッドが呼び出されません。これはほとんどの場合に発生します。

一度に実行できる AsyncTasks には制限があることをご存知ですか? 以前、タスクが正しく開始/動作しないという問題がありましたが、これはその数を超えたことが原因でした。Android AsyncTask スレッドの制限を確認しますか? そのトピックの詳細については。

そのアクティビティのバックグラウンドでサービスが実行されたとき。たとえば、音楽がサービスを使用してバックグラウンドで実行されている場合、非同期タスクはバックグラウンドで XML を解析しません。これは、その doInBackground がその時点で機能せず、progress Dialog または progressBar が回転し続けたためです。

デッドロックの可能性を確認しましたか (特に、 および を使用している場合wait()) notify()

まあ、問題は「サービスはメインスレッドで実行されるため、実行するとAsyncTaskの実行がブロックされる」ためだと思います...したがって、サービスをバックグラウンドスレッドで実行できれば、それが役立つと思います. だから私は

サービスで行うことは、とにかく独自のスレッドで実行する必要があります。そうすれば、何もブロックされないことを確認できます。たとえば、入力するものがある場合は、レシーバーを使用できます。

少しでもお役に立てれば幸いです...

于 2013-02-23T18:46:44.427 に答える
1

ここにヒントがあります。私が最終的に問題を解決した方法::

1) Service の代わりに IntentServiceを使用しました。サービスは mainThread で実行されますが、IntentService は mainThread とは別の Thread で実行され、バックグラウンドの Service が現在のタスクに影響を与えないようにします。また、UI とバックグラウンド スレッド間の通信に AIDL を使用しています (これはすでに Service で機能しているため、この部分では新しいことは何もありません)。

2) AsyncTask の代わりに痛みのないスレッドを使用しました。スレッドが無期限に継続することを確認するために、 onDestroy()メソッドでスレッドを中断しました。

アプリのパフォーマンスは以前よりもはるかに優れているようです。

これが他の人にも役立つことを願っています:)

于 2013-02-25T07:35:01.983 に答える
1

GetData AsyncTask問題は、前の問題が完了する前に別の問題が発生していると思います。別のタスクを実行する前に、前のタスクが完了していることを確認してください。これを行うには、次のコードを使用します。

// make sure we don't collide with another pending AsyncTask
if (getDataTask == null || getDataTask.getStatus() == AsyncTask.Status.FINISHED || getDataTask.isCancelled()) {
    getDataTask= new GetData();
    getDataTask.execute();
} 

また、タスクを実行するための参照があることを確認してください。アプリケーションの実行中にクラスのサブクラスを使用Applicationしてこれを行うか、オーバーライドonSaveInstanceState(Bundle outState) して で参照を受け取ることができますonCreate(Bundle savedInstanceState)

于 2013-02-21T17:30:26.930 に答える
0

Android Developer AsyncTask ドキュメントの Threading Rules セクションによるAsyncTaskと、UI スレッドで を作成して起動する必要があるため、サービスのバックグラウンド スレッドから起動する場合、それが問題のある動作の原因になります。

http://developer.android.com/reference/android/os/AsyncTask.html

于 2013-02-22T04:42:16.663 に答える
-2

一般的に AsyncTasks を使用するべきではありません :)ここにかなり良い説明があります。タスクの実行中にユーザーがデバイスを回転させた場合に何が起こるかを考えてください。アクティビティは再作成されますが、タスクはバックグラウンドで実行され、「古い」アクティビティへの参照が保持されます。これを回避する方法はありますが、AsyncTasks が正しいアプローチである場合も確かにあります。

ただし、ローダーへの切り替えを検討するか、(冒険好きなら) RoboSpiceを試す必要があります:)

于 2013-02-22T09:04:54.013 に答える