本文介绍了Android SDK中的AsyncTask doInBackground没有运行(子)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

截至15/2/2012我还没有找到一个很好的解释,也没有一个原因,这是行不通的。最接近一个解决方案是使用传统的螺纹的方法,但为什么包括不类(似乎在Android SDK)的工作?

EveninSO!

我有一个AsyncTask的子类:

  // ParseListener有一个回调这是所谓的,当一个项目被解析的
// RSS-XML,但表示进一步下跌则根本不使用现在。
私有类xmlAsync扩展的AsyncTask<字符串的RSSItem,太虚>实现ParseListener
 

这是这样执行的:

  xmlAsync xmlThread =新xmlAsync();

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

现在这个子又碰上一个小错误。 previously它做了一些XML解析,但是当我发现它的 doInBackground()不叫我剥离下来,一行行,终于结束了只有这一点:

  @覆盖
保护无效doInBackground(字符串... PARAMS)
{
    Log.v(TAG,doInBackground);
        返回null;
}
 

其中,由于某种原因,记录什么。不过,我补充这一点:

  @覆盖
在preExecute保护无效()
{
        Log.v(TAG,在preExecute);
        super.on preExecute();
}
 

和执行线程时,确实记录该行。 所以,不知何故在preExecute()被调用,但不doInBackground()。我还有一个AsyncTask的背景,同时它工作得很好运行。

我目前正在运行的应用程序在仿真器,SDK版本15时,Eclipse的Mac OS X 10.7.2,接近北极点。

编辑:

  @覆盖
    保护无效onProgressUpdate(的RSSItem ...值){

        如果(值[0] == NULL)
        {
                            //活动的函数,它仅仅是创建一个对话框
            showInputError();
        }
        其他
        {

            Log.v(TAG,并称+值[0]的ToString());
            _tableManager.addRSSItem(值[0]);
        }


        super.onProgressUpdate(值);
    }
 

_tableManager.addRSSItem()或多或少添加行到一个SQLiteDatabase,与该活动的背景下进行初始化。 publishProgress()被调用的接口ParseListener的回调。然而,因为我甚至不只是log.v在doInBackground()做任何事情,我第一次发现这是不必要的,甚至带来了起来。

编辑2:

好了,只是要非常清楚,这是其他AsyncTask的,在执行相同的活动和工作完美的罚款。

 私有类dbAsync扩展的AsyncTask<太虚,RSSItem中,太虚>
{
    整数prevCount;
    布尔运行;

    @覆盖
    在preExecute保护无效(){
        运行=真;
        super.on preExecute();
    }

    @覆盖
    保护无效doInBackground(虚空...... PARAMS){
        // TODO自动生成方法存根
        运行=真;
        prevCount = 0;

        而(运行)
        {
            ArrayList的<的RSSItem>项= _tableManager.getAllItems();

            如果(项目!= NULL)
            {
                如果(items.size()> prevCount)
                {
                    Log.v(DB主题,找到新的项目(S)!);
                    prevCount = items.size();

                    的RSSItem [] itemsArray =新的RSSItem [items.size()];

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

            SystemClock.sleep(5000);
        }

        返回null;
    }

    @覆盖
    保护无效onProgressUpdate(的RSSItem ...值){

        ArrayList的<的RSSItem>名单=新的ArrayList<的RSSItem>();

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

        setItemsAndUpdateList(名单);

        super.onProgressUpdate(值);
    }

    @覆盖
    保护无效onCancelled(){
        运行= FALSE;

        super.onCancelled();
    }
}
 

修改3:

唉,对不起,是我不好,在问问题。但这里是任务的初始化。

  xmlAsync _xmlParseThread;
dbAsync _dbLookup;

/ **第一次创建活动时调用。 * /
@覆盖
公共无效的onCreate(包savedInstanceState){
super.onCreate(savedInstanceState);
的setContentView(R.layout.main);

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

_xmlParseThread =新xmlAsync();
_xmlParseThread.execute(http://www.nothing.com,NULL);
}
 

解决方案

马蒂厄的解决方案能够适用于大多数,但有些可能面临的问题;除非挖这里提供了很多链接或网页,像Anders Göransson的解释。我试图总结出一些其他的读取这里并迅速解释解决方案,如果executeOnExecutor仍然是工作在单线程...

的AsyncTask的行为()执行(); 已经通过Android的版本进行了更改。之前的甜甜圈 (安卓1.6 API:4)的任务是串行执行,从甜甜圈姜饼 (安卓2.3 API:9)的任务并行执行;由于蜂窝 (安卓3.0 API:11)的执行被切换回顺序;一种新的方法 AsyncTask的()。executeOnExecutor(执行器)然而,加入了并行执行。

在顺序处理在一个线程中运行的所有异步任务,并由此有previous任务结束前等待的时间。如果您需要立即执行code,你需要的任务在并行独立的线程处理。

使用AsyncTask的串行执行不可用甜甜圈和蜂窝版本之间,而并行执行不可用甜甜圈了。

有关并行处理后的甜甜圈:检查生成版本以及基于,请使用.execute()或.executeOnExecutor()方法。继code可以帮助...

 的AsyncTask<虚空,虚空,虚空> MyTask的=新的AsyncTask<虚空,虚空,虚空>(){...}; // ...您的AsyncTask code到这里
如果(Build.VERSION.SDK_INT> = Build.VERSION_ codeS.HONEYCOMB)
    myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
其他
    myTask.execute();
 

注:功能 .executeOnExecutor()有检查,如果 targetSdkVersion 小于或等于 HONEYCOMB_MR1 (安卓2.1 API:7),那么它会强制执行程序是 THREAD_POOL_EXECUTOR (这在蜂窝后任务运行顺序)。
如果你还没有定义的 targetSdkVersion 然后的minSdkVersion 被自动认为是 targetSdkVersion
因此,对于在蜂窝后运行的AsyncTask的并行你不能离开 targetSdkVersion 空。

As of 15/2/2012 I have yet to find a good explanation to nor a reason why this does not work. The closest to a solution is to use the traditional Thread approach, but then why include a class that does not (seem to) work in the Android SDK?

Evenin' SO!

I have an AsyncTask subclass:

// 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

That is executed like this:

xmlAsync xmlThread = new xmlAsync();

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

Now this subclass has run into a little error. Previously it did some xml-parsing, but when I noticed that it's doInBackground() wasn't called I stripped it down, line by line, finally ending up with just this:

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

Which, for some reason, logged nothing. However, I added this:

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

And that line is indeed logged when executing the thread. So somehow onPreExecute() is called but not doInBackground(). I have another AsyncTask running in the background at the same time which works just fine.

I'm currently running the app on an emulator, SDK Version 15, Eclipse, Mac OS X 10.7.2, close to the North Pole.

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() more or less adds a row to a SQLiteDatabase, initialized with the activity's context. publishProgress() is called by the Interface ParseListener's callback. However, since I don't even do anything except log.v in doInBackground() I first found this unnecessary to even bring up.

EDIT 2:

Alright, just to be perfectly clear, this is the other AsyncTask, executing in the same activity and working perfectly fine.

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:

Sigh, sorry I'm bad at asking questions. But here is the initialization of the Tasks.

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's solution will work fine for most, but some can face problem; unless digging in many links provided here or from web, like Anders Göransson's explanation.I am trying to summarize some other reads right here and quickly explain solution if executeOnExecutor is still working in single thread...

Behavior of AsyncTask().execute(); has changed through Android versions. Before Donut (Android:1.6 API:4) tasks were executed serially, from Donut to Gingerbread (Android:2.3 API:9) tasks executed paralleled; since Honeycomb (Android:3.0 API:11) execution was switched back to sequential; a new method AsyncTask().executeOnExecutor(Executor) however, was added for parallel execution.

In sequential processing all Async tasks run in a single thread and thus have to wait before the previous task ends. If you need to execute code immediately, you need tasks to be processed in parallel in separate threads.

With AsyncTask serial execution is not available between Donut and Honeycomb versions, while parallel execution is not available before Donut.

For parallel processing after Donut: Check the Build version and based on that use .execute() or .executeOnExecutor() method. Following code can help...

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: Function .executeOnExecutor() has checks if targetSdkVersion of project is less than or equal to HONEYCOMB_MR1 (Android:2.1 API:7) then it forces the executor to be THREAD_POOL_EXECUTOR (which runs Tasks sequentially in post Honeycomb).
If you have not defined a targetSdkVersion then minSdkVersion is automatically considered to be the targetSdkVersion.
Hence for running your AsyncTask in parallel on post Honeycomb you cannot leave targetSdkVersion empty.

这篇关于Android SDK中的AsyncTask doInBackground没有运行(子)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 12:49
查看更多