Android SDK AsyncTask doInBackground未运行(子类)

古之立大事者,不惟有超世之才,亦必有坚忍不拔之志。这篇文章主要讲述Android SDK AsyncTask doInBackground未运行(子类)相关的知识,希望能为你提供帮助。
截至2012年2月15日,我还没有找到一个很好的解释,也不知道为什么这不起作用。最接近解决方案的是使用传统的Thread方法,但为什么要包含一个在android SDK中没有(似乎)工作的类?
Evenin'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-parsing,但是当我注意到它的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版本15,Eclipse,Mac OS X 10.7.2,靠近北极。
编辑:
@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添加一行,并使用activity的上下文进行初始化。 publishProgress()由Interface ParseListener的回调调用。但是,因为除了doInBackground()中的log.v之外我甚至都没有做任何事情,所以我首先发现这甚至没有提起来。
编辑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(); } }

编辑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版本发生了变化。 Donut(Android:1.6 API:4)之前的任务是连续执行的,从Donut到Gingerbread(Android:2.3 API:9)任务并行执行; 因为Honeycomb(Android:3.0 API:11)执行被切换回顺序; 然而,一个新方法AsyncTask().executeOnExecutor(Executor)被添加用于并行执行。
在顺序处理中,所有异步任务都在单个线程中运行,因此必须在上一个任务结束之前等待。如果需要立即执行代码,则需要在单独的线程中并行处理任务。
使用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(在后蜂窝中顺序运行任务)。 如果你还没有定义targetSdkVersion那么minSdkVersion自动被认为是targetSdkVersion。 因此,为了在后蜂窝上并行运行AsyncTask,你不能将targetSdkVersion留空。
另一答案你应该检查这个答案:https://stackoverflow.com/a/10406894/347565和它包含的谷歌组的链接。
我遇到了类似的问题,仍然不清楚为什么它不起作用,但我改变了我的代码并且问题消失了:
ASyncTask< Void,Void,Void> my_task = new ASyncTask< Void,Void,Void> () { ... }; if (Build.VERSION.SDK_INT > = Build.VERSION_CODES.HONEYCOMB) my_task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null); else my_task.execute((Void[])null);

另一答案你可以通过两种方式做到这一点:
方式1:
if(Build.VERSION.SDK_INT> =Build.VERSION_CODES.HONEYCOMB) // Above Api Level 13 { asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } else // Below Api Level 13 { asyncTask.execute(); }

如果方式1不适合你,请尝试方式2。
方式2:
int mCorePoolSize = 60; int mMaximumPoolSize = 80; int mKeepAliveTime = 10; BlockingQueue< Runnable> workQueue = new LinkedBlockingQueue< Runnable> (mMaximumPoolSize); Executor mCustomThreadPoolExecutor = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, mKeepAliveTime, TimeUnit.SECONDS, workQueue); asyncTask.executeOnExecutor(mCustomThreadPoolExecutor);

希望这会帮助你。
另一答案我遇到了同样的问题:在第一个调用“execute”之后无法执行第二个AsyncTask:doInBackground只调用第一个。
要回答为什么会发生这种情况,请检查此answer(根据SDK的不同行为)
但是,对于您的情况,使用executeOnExecutor可以避免这个障碍(从3.0开始可用,使用4.0.3为我工作)但要注意线程池大小和排队的限制。
【Android SDK AsyncTask doInBackground未运行(子类)】你能尝试这样的事吗:
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.executeOnExecutor(_dbLookup.THREAD_POOL_EXECUTOR ,"http://www.nothing.com", null); }

对于你的更新问题:它在docs中解释基本上只是为了避免可能来自多线程的所有问题,如干扰....
另一答案我想知道的一件事,它可能实际上解决了你的问题,你在哪里实例化你的类的实例并调用execute()方法?如果您阅读AsyncTask的文档,则这两个操作都需要在主UI线程上进行。如果你正在创建你的对象并从其他一些线程调用execute,那么onPreExecute可能会触发,我不是100%肯定在这里,但后台线程将不会被创建和执行。
如果要从后台线程创建AsyncTask实例,或者在主UI线程上没有进行其他操作,可以考虑使用以下方法:Activity.runOnUiThread(Runnable)
您需要访问正在运行的Activity的实例来调用该方法,但它将允许您从UI线程上未运行的其他代码运行UI线程上的代码。
希望有道理。如果我能提供更多帮助,请告诉我。
大卫
另一答案Android是野蛮的!我无法相信这一点,从白天到今天的变化是什么样的变化。有一天是单线程,下一个是5,另一个是128。
无论如何,这里的AsyncTask股票几乎没有替代品。如果你愿意,你甚至可以称它为AsyncTask,但为了避免混淆它的名为ThreadedAsyncTask。您需要调用executeStart()而不是execute,因为execute()是最终的。
/** * @author Kevin Kowalewski * */ public abstract class ThreadedAsyncTask< Params, Progress, Result> extends AsyncTask< Params, Progress, Result> { public AsyncTask< Params, Progress, Result> executeStart(Params... params){ if (Build.VERSION.SDK_INT > = Build.VERSION_CODES.HONEYCOMB){ return executePostHoneycomb(params); }else{ return super.execute(params); } }@TargetApi(Build.VERSION_CODES.HONEYCOMB) private AsyncTask< Params, Progress, Result> executePostHoneycomb(Params... params){ return super.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params); } }

另一答案我知道这可能对于线程来说真的很晚,但是有一个原因导致它不适用于以后的android模拟器。当asynctask被引入时,android只允许你一次运行一个,然后一段时间后,我不确定哪个版本,它们允许你一次运行多个asynctasks,这导致很多应用程序出现问题,所以在Honeycomb +中它们只恢复到允许一个asynctask一次运行。除非您手动更改线程池。希望为人们清除一两件事。
另一答案我认为它是sdk。我遇到了同样的问题,在将目标sdk从15改为11之后,一切都运行良好。
使用sdk15,即使AsyncTask.Status是RUNNING,也永远不会调用doInBackground。我确实认为它与ui线程有关。
另一答案根据Matthieu的回答,在帮助程序类下方根据SDK版本正确执行AsyncTask,以避免在应用程序中重复代码:
import android.annotation.SuppressLint; import android.os.AsyncTask; import android.os.Build; public class AsyncTaskExecutor< Params, Progress, Result> {@SuppressLint("NewApi") public AsyncTask< Params, Progress, Result> execute(final AsyncTask< Params, Progress, Result> asyncTask, final Params... params){ if (Build.VERSION.SDK_INT > = Build.VERSION_CODES.HONEYCOMB){ return asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params); }else{ return asyncTask.execute(params); } }}

使用示例:
public class MyTask extends AsyncTask< Void, Void, List< String> > {

...
final MyTask myTask = new MyTask(); new AsyncTaskExecutor< Void, Void, List< String> > ().execute(myTask);


    推荐阅读