Java 防止AsyncTask在bindView中多次运行
我有一个自定义的Java 防止AsyncTask在bindView中多次运行,java,android,android-asynctask,android-cursoradapter,Java,Android,Android Asynctask,Android Cursoradapter,我有一个自定义的CursorAdapter,它在bindView方法中使用多个AsyncTasks将图像加载到网格中 当bindView运行我的AsyncTasks时,会多次启动。这会增加堆大小,并可能导致内存不足错误 让AsyncTasks只运行一次的最佳方法是什么?您可以缓存AsyncTask的结果。在Github上有一个非常有用的项目,您可能想研究一下。我想您正在寻找它或它的实现。它为你处理一切 如何使用它的示例: public SampleLoader extends AsyncTask
CursorAdapter
,它在bindView
方法中使用多个AsyncTask
s将图像加载到网格中
当bindView
运行我的AsyncTask
s时,会多次启动。这会增加堆大小,并可能导致内存不足错误
让
AsyncTask
s只运行一次的最佳方法是什么?您可以缓存AsyncTask的结果。在Github上有一个非常有用的项目,您可能想研究一下。我想您正在寻找它或它的实现。它为你处理一切
如何使用它的示例:
public SampleLoader extends AsyncTaskLoader<List<SampleItem>> {
// We hold a reference to the Loader’s data here.
private List<SampleItem> mData;
public SampleLoader(Context ctx) {
// Loaders may be used across multiple Activitys (assuming they aren't
// bound to the LoaderManager), so NEVER hold a reference to the context
// directly. Doing so will cause you to leak an entire Activity's context.
// The superclass constructor will store a reference to the Application
// Context instead, and can be retrieved with a call to getContext().
super(ctx);
}
/****************************************************/
/** (1) A task that performs the asynchronous load **/
/****************************************************/
@Override
public List<SampleItem> loadInBackground() {
// This method is called on a background thread and should generate a
// new set of data to be delivered back to the client.
List<SampleItem> data = new ArrayList<SampleItem>();
// TODO: Perform the query here and add the results to 'data'.
return data;
}
/********************************************************/
/** (2) Deliver the results to the registered listener **/
/********************************************************/
@Override
public void deliverResult(List<SampleItem> data) {
if (isReset()) {
// The Loader has been reset; ignore the result and invalidate the data.
releaseResources(data);
return;
}
// Hold a reference to the old data so it doesn't get garbag ecollected.
// We must protect it until the new data has been delivered.
List<SampleItem> oldData = mData;
mData = data;
if (isStarted()) {
// If the Loader is in a started state, deliver the results to the
// client. The superclass method does this for us.
super.deliverResult(data);
}
// Invalidate the old data as we don't need it any more.
if (oldData != null && oldData != data) {
releaseResources(oldData);
}
}
/*********************************************************/
/** (3) Implement the Loader’s state-dependent behavior **/
/*********************************************************/
@Override
protected void onStartLoading() {
if (mData != null) {
// Deliver any previously loaded data immediately.
deliverResult(mData);
}
// Begin monitoring the underlying data source.
if (mObserver == null) {
mObserver = new SampleObserver();
// TODO: register the observer
}
if (takeContentChanged() || mData == null) {
// When the observer detects a change, it should call onContentChanged()
// on the Loader, which will cause the next call to takeContentChanged()
// to return true. If this is ever the case (or if the current data is
// null), we force a new load.
forceLoad();
}
}
@Override
protected void onStopLoading() {
// The Loader is in a stopped state, so we should attempt to cancel the
// current load (if there is one).
cancelLoad();
// Note that we leave the observer as is. Loaders in a stopped state
// should still monitor the data source for changes so that the Loader
// will know to force a new load if it is ever started again.
}
@Override
protected void onReset() {
// Ensure the loader has been stopped.
onStopLoading();
// At this point we can release the resources associated with 'mData'.
if (mData != null) {
releaseResources(mData);
mData = null;
}
// The Loader is being reset, so we should stop monitoring for changes.
if (mObserver != null) {
// TODO: unregister the observer
mObserver = null;
}
}
@Override
public void onCanceled(List<SampleItem> data) {
// Attempt to cancel the current asynchronous load.
super.onCanceled(data);
// The load has been canceled, so we should release the resources
// associated with 'data'.
releaseResources(data);
}
private void releaseResources(List<SampleItem> data) {
// For a simple List, there is nothing to do. For something like a Cursor, we
// would close it in this method. All resources associated with the Loader
// should be released here.
}
/*********************************************************************/
/** (4) Observer which receives notifications when the data changes **/
/*********************************************************************/
// NOTE: Implementing an observer is outside the scope of this post (this example
// uses a made-up "SampleObserver" to illustrate when/where the observer should
// be initialized).
// The observer could be anything so long as it is able to detect content changes
// and report them to the loader with a call to onContentChanged(). For example,
// if you were writing a Loader which loads a list of all installed applications
// on the device, the observer could be a BroadcastReceiver that listens for the
// ACTION_PACKAGE_ADDED intent, and calls onContentChanged() on the particular
// Loader whenever the receiver detects that a new application has been installed.
// Please don’t hesitate to leave a comment if you still find this confusing! :)
private SampleObserver mObserver;
}
publicSampleLoader扩展了AsyncTaskLoader{
//我们在这里保存了装载机数据的引用。
私有列表数据;
公共样本加载器(上下文ctx){
//装载机可以跨多个活动使用(假设它们不是
//绑定到LoaderManager),因此永远不要保留对上下文的引用
//直接。这样做会导致泄漏整个活动的上下文。
//超类构造函数将存储对应用程序的引用
//相反,可以通过调用getContext()来检索。
超级(ctx);
}
/****************************************************/
/**(1)执行异步加载的任务**/
/****************************************************/
@凌驾
公共列表加载背景(){
//此方法在后台线程上调用,并应生成
//要传递回客户端的新数据集。
列表数据=新的ArrayList();
//TODO:在此处执行查询并将结果添加到“数据”中。
返回数据;
}
/********************************************************/
/**(2)将结果传递给注册的侦听器**/
/********************************************************/
@凌驾
公共无效交付结果(列表数据){
if(isReset()){
//加载程序已重置;忽略结果并使数据无效。
发布资源(数据);
返回;
}
//保留对旧数据的引用,这样它就不会被收集。
//在新数据交付之前,我们必须保护它。
List oldData=mData;
mData=数据;
如果(isStarted()){
//如果加载程序处于启动状态,则将结果传递给
//超类方法为我们做到了这一点。
super.deliverResult(数据);
}
//使旧数据无效,因为我们不再需要它了。
if(oldData!=null&&oldData!=data){
释放资源(旧数据);
}
}
/*********************************************************/
/**(3)实现加载器的状态相关行为**/
/*********************************************************/
@凌驾
开始加载时受保护的void(){
如果(mData!=null){
//立即交付以前加载的任何数据。
交付结果(mData);
}
//开始监视基础数据源。
if(mObserver==null){
mObserver=新的SampleObserver();
//TODO:注册观察者
}
if(takeContentChanged()| | mData==null){
//当观察者检测到更改时,它应该调用onContentChanged()
//在加载程序上,这将导致对takeContentChanged()的下一次调用
//返回true。如果是这种情况(或者如果当前数据为
//null),我们强制一个新的加载。
力载荷();
}
}
@凌驾
受保护的无效onStopLoading(){
//加载程序处于停止状态,因此我们应该尝试取消
//当前负载(如果有)。
取消加载();
//请注意,我们将观察者保持原样。加载程序处于停止状态
//仍应监视数据源的更改,以便加载程序
//如果再次启动,将知道强制加载新负载。
}
@凌驾
受保护的void onReset(){
//确保装载机已停止。
onStopLoading();
//此时,我们可以释放与“mData”关联的资源。
如果(mData!=null){
释放资源(mData);
mData=null;
}
//加载程序正在重置,因此我们应该停止监视更改。
if(mObserver!=null){
//TODO:取消注册观察者
mObserver=null;
}
}
@凌驾
已取消公共作废(列表数据){
//尝试取消当前异步加载。
super.onCanceled(数据);
//加载已取消,因此我们应该释放资源
//与“数据”关联。
发布资源(数据);
}
私有void releaseResources(列表数据){
//对于一个简单的列表,没有什么可以做的
//将在此方法中关闭它。与加载程序关联的所有资源
//应该在这里发布。
}
/*********************************************************************/
/**(4)当数据发生变化时接收通知的观察者**/
/*********************************************************************/
//注意:实现一个观察者超出了本文的范围(本例)
//使用虚构的“SampleObserver”来说明观察者应在何时/何地进行观察
//(无法初始化)。
//观察者可以是任何东西,只要它能够检测到内容的变化
//并通过调用onContentChanged()将它们报告给加载程序。例如,
//如果您正在编写加载所有已安装应用程序列表的加载程序
//在该设备上,观察者可以是一个广播接收器,用于监听信号
//ACTION_PACKAGE_添加了意图,并对特定的
//每当接收器检测到新应用程序已安装时,加载程序。
//如果您仍然感到困惑,请随时发表评论!:)
私有采样服务器;
}
来源:使用
加载程序
,如前所述@