1. ホーム
  2. android

[解決済み] Android SDK AsyncTask doInBackground が実行されない (サブクラス)

2023-03-24 22:46:41

質問

2012年2月15日現在、私はまだこれが機能しない理由に対する良い説明や理由を見つけることができません。解決策に最も近いのは、従来の スレッド アプローチですが、それではなぜAndroid SDKで動作しない(ように見える)クラスをインクルードするのでしょうか?

こんばんは、SO!

AsyncTaskのサブクラスを持っています。

// ParseListener had a callback which was called when an item was parsed in a
// RSS-xml, but as stated further down it is not used at all right now.
private class xmlAsync extends AsyncTask<String, RSSItem, Void> implements ParseListener

それがこのように実行されます。

xmlAsync xmlThread = new xmlAsync();

xmlThread.execute("http://www.nothing.com");

さて、このサブクラスはちょっとしたエラーに見舞われました。以前は xml パースを行っていましたが、気づいたときには doInBackground() が呼び出されていないことに気づいたとき、私はそれを一行ずつ削除し、最終的にこれだけになりました。

@Override
protected Void doInBackground(String... params) 
{
    Log.v(TAG, "doInBackground");
        return null;
}

これは、なぜか何もログに残りません。しかし、私はこれを追加しました。

@Override
protected void onPreExecute() 
{
        Log.v(TAG, "onPreExecute");
        super.onPreExecute();
}

そしてその行は、スレッドを実行する際に確かにログに記録されます。 つまり、どういうわけか onPreExecute() は呼び出されますが、doInBackground() は呼び出されないのです。 . 私は同時にバックグラウンドで実行されている別のAsyncTaskを持っており、それはうまく動作しています。

私は現在、SDK Version 15、Eclipse、Mac OS X 10.7.2 のエミュレーター上で、北極に近い場所でアプリを実行しています。

EDITです。

@Override
    protected void onProgressUpdate(RSSItem... values) {

        if(values[0] == null)
        {
                            // activity function which merely creates a dialog
            showInputError();
        }
        else
        {

            Log.v(TAG, "adding "+values[0].toString());
            _tableManager.addRSSItem(values[0]);
        }


        super.onProgressUpdate(values);
    }

_tableManager.addRSSItem() は多かれ少なかれ、アクティビティのコンテキストで初期化された SQLiteDatabase に行を追加します。publishProgress() は Interface ParseListener のコールバックによって呼び出されます。しかし、私はdoInBackground()でlog.vを除いて何もしないので、私は最初にこれを持ち出すことさえ不要であることがわかりました。

EDIT 2:

さて、完全に明確にするために、これは他のAsyncTaskであり、同じアクティビティで実行され、完全にうまく動作しています。

private class dbAsync extends AsyncTask<Void, RSSItem, Void>
{
    Integer prevCount;
    boolean run;

    @Override
    protected void onPreExecute() {
        run = true;
        super.onPreExecute();
    }

    @Override
    protected Void doInBackground(Void... params) {
        // TODO Auto-generated method stub
        run = true;
        prevCount = 0;

        while(run)
        {
            ArrayList<RSSItem> items = _tableManager.getAllItems();

            if(items != null)
            {
                if(items.size() > prevCount)
                {
                    Log.v("db Thread", "Found new item(s)!");
                    prevCount = items.size();

                    RSSItem[] itemsArray = new RSSItem[items.size()];

                    publishProgress(items.toArray(itemsArray));
                }
            }               

            SystemClock.sleep(5000);
        }

        return null;
    }

    @Override
    protected void onProgressUpdate(RSSItem... values) {

        ArrayList<RSSItem> list = new ArrayList<RSSItem>();

        for(int i = 0; i < values.length; i++)
        {
            list.add(i, values[i]);
        }

        setItemsAndUpdateList(list);

        super.onProgressUpdate(values);
    }

    @Override
    protected void onCancelled() {
        run = false;

        super.onCancelled();
    }
}

EDIT 3:

はぁ~、質問下手ですいません。でも、タスクの初期化はこんな感じです。

xmlAsync _xmlParseThread;
dbAsync _dbLookup;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

_dbLookup = new dbAsync();
_dbLookup.execute();

_xmlParseThread = new xmlAsync();       
_xmlParseThread.execute("http://www.nothing.com", null);
}

どのように解決するのですか?

Matthieu の解決策は、ほとんどの場合うまくいきますが、一部の人は問題に直面する可能性があります。 Anders Göransson の説明のように。 私はここで他の記事を要約し、executeOnExecutorがまだシングルスレッドで動作している場合の解決策をすばやく説明しようとしています...

の挙動 AsyncTask().execute(); の挙動は、Androidのバージョンによって変化しています。以前は ドーナツ (アンドロイド:1.6 API:4) のタスクが順次実行されました。 ドーナツ から ジンジャーブレッド (Android:2.3 API:9) タスクが並列に実行されるようになりました。 ハニカム (アンドロイド:3.0 API:11) の実行がシーケンシャルに戻され、新しいメソッド AsyncTask().executeOnExecutor(Executor) が追加され、並列実行が可能になりました。

逐次処理では、すべての Async タスクは単一のスレッドで実行されるため、前のタスクが終了する前に待機する必要があります。すぐにコードを実行する必要がある場合、タスクは別々のスレッドで並列に処理される必要があります。

AsyncTask のシリアル実行は Donut と Honeycomb バージョンの間では利用できず、一方、並列実行は Donut よりも前に利用できません。

Donut以降の並列処理について。Buildのバージョンを確認し、それに基づいて.execute()または.executeOnExecutor()メソッドを使用します。以下のコードが参考になります。

AsyncTask<Void,Void,Void> myTask = new AsyncTask<Void,Void,Void>() { ... }; // ... your AsyncTask code goes here
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB)
    myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
    myTask.execute();

NOTE: 機能 .executeOnExecutor()targetSdkVersion と同じかそれ以下であるかどうかを調べます。 HONEYCOMB_MR1 (Android:2.1 API:7)であれば、強制的にエグゼキュータが THREAD_POOL_EXECUTOR (ポストHoneycombでTasksを順次実行する)となります。

を定義していない場合は targetSdkVersion であれば minSdkVersion は自動的に targetSdkVersion .

したがって、ポストハニカムのAsyncTaskを並列に実行するために targetSdkVersion を空にすることはできません。