0

所以基本上,让我设置场景:

List<Account> accounts = ...//Initialised with 2 accounts.

for( Account ac : accounts)
{
   new AsyncTask<...>(){ getTwitterTimeLine(amount);}.execute();
}

所以你可以在这里看到两个 AsyncTask 被一个接一个地调用。

现在这是有趣的部分,

如果我将数量变量设置为 10。该方法调用一个 HTTP 请求,请求 10 个最新的提要项。这工作得很好,正常的行为是将返回的数据放入多个可能的列表视图之一中,(所有都可以通过 viewpager 查看,因此在这种情况下,2 个列表视图分别由 2 个异步任务填充)

如果我把数量设置为 100,那么基本上更多的 JSON 数据,我得到以下内容;

   04-04 03:11:20.175: E/AndroidRuntime(4574): FATAL EXCEPTION: AsyncTask #1
04-04 03:11:20.175: E/AndroidRuntime(4574):     at android.os.AsyncTask$3.done(AsyncTask.java:299)
04-04 03:11:20.175: E/AndroidRuntime(4574):     at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
04-04 03:11:20.175: E/AndroidRuntime(4574):     at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
04-04 03:11:20.175: E/AndroidRuntime(4574):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
04-04 03:11:20.175: E/AndroidRuntime(4574):     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
04-04 03:11:20.175: E/AndroidRuntime(4574):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
04-04 03:11:20.175: E/AndroidRuntime(4574):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
04-04 03:11:20.175: E/AndroidRuntime(4574):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
04-04 03:11:20.175: E/AndroidRuntime(4574):     at java.lang.Thread.run(Thread.java:856)
04-04 03:11:20.175: E/AndroidRuntime(4574): Caused by: java.lang.OutOfMemoryError
04-04 03:11:20.175: E/AndroidRuntime(4574):     at 

java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:94)
04-04 03:11:20.175: E/AndroidRuntime(4574):     at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:145)
04-04 03:11:20.175: E/AndroidRuntime(4574):     at java.lang.StringBuilder.append(StringBuilder.java:216)
04-04 03:11:20.175: E/AndroidRuntime(4574):     at twitter4j.internal.org.json.JSONArray.join(JSONArray.java:363)
04-04 03:11:20.175: E/AndroidRuntime(4574):     at twitter4j.internal.org.json.JSONArray.toString(JSONArray.java:605)
04-04 03:11:20.175: E/AndroidRuntime(4574):     at twitter4j.internal.http.HttpResponse.asJSONArray(HttpResponse.java:192)
04-04 03:11:20.175: E/AndroidRuntime(4574):     at twitter4j.internal.json.StatusJSONImpl.createStatusList(StatusJSONImpl.java:381)
04-04 03:11:20.175: E/AndroidRuntime(4574):     at twitter4j.internal.json.z_T4JInternalJSONImplFactory.createStatusList(z_T4JInternalJSONImplFactory.java:74)
04-04 03:11:20.175: E/AndroidRuntime(4574):     at twitter4j.TwitterImpl.getHomeTimeline(TwitterImpl.java:127)

它直接指向我的 AsyncTask 的 doInBackground 方法,在该方法中调用 getTwitterTimeLine()。

我该如何解决这个问题?我希望能够引入大量数据,并将其泵送到多个列表视图等。我阅读了很多,我想也许我需要将任务排队,以防其中一个占用大量内存,所以我研究并使用正确使用 AsyncTask,但这没有效果,我仍然遇到内存不足的问题。

无论如何如何解决/解决这个问题?我阅读了 LoaderManager,但我想将其推迟到最后一次调用,因为它会导致重大的设计更改。

感谢您的任何帮助。

注意:getTwitterTimeLine 方法调用调用 api 的 twitter4j 方法。

4

3 回答 3

1

您不想像这样在循环中触发 AsyncTask。有一个固定的线程池大小,虽然两个帐户左右不足以将其最大化,但最好不要这样做。相反,请确定如何在单个异步任务中加载所有这些数据。doInBackground() 接受参数列表。例如,您可以使用构造函数中设置的数量创建 AsyncTask 并传入帐户以加载数据。

@Override
protected Map<Account, Data> doInBackground(Accounts...params){
    Map<Account, Data> resultMap = new HashMap<Account, Data>();
    for (Account account : params) {
        // do whatever!
    }
    return resultMap;
}
于 2013-04-04T03:34:09.953 回答
1

您不能依赖AsyncTasks 进行并行执行

首次引入时,AsyncTask 在单个后台线程上串行执行。从 DONUT 开始,这被更改为允许多个任务并行运行的线程池。从 HONEYCOMB 开始,任务在单个线程上执行,以避免并行执行导致的常见应用程序错误。

至于 twitter4j...

at java.lang.StringBuilder.append(StringBuilder.java:216)
04-04 03:11:20.175: E/AndroidRuntime(4574):     at twitter4j.internal.org.json.JSONArray.join(JSONArray.java:363)

...它在内部使用 StringBuilder。在内存有限的设备上跨多个线程使用字符串连接必然会导致 OOM。如果您想节省这些 json 字符串占用的内存,请改用JsonReader。至于并行执行,您可以使用由ThreadPool支持的线程来并行执行它们。AsyncTasks 在某些版本的 android 中是串行执行的。

于 2013-04-04T04:34:00.993 回答
0

事实证明,最终是因为位图没有被内存管理。尽管实现了 android 开发页面描述的 inSampleSize 框架以有效地加载位图,但似乎适当地维护和管理它们是必要的。

感谢所有回复的人,主题非常丰富。

于 2013-04-04T12:00:45.190 回答