Android-取消注册适配器中定义的ContentObserver

Android-取消注册适配器中定义的ContentObserver,android,listview,android-cursoradapter,contentobserver,Android,Listview,Android Cursoradapter,Contentobserver,我有一系列文件要上传。这些内容作为条目存储在内容提供程序中。每个条目还包含上载的百分比 一个活动显示上载列表,每个文件都是一个项目,带有进度条以显示上载进度 我更新进度条的方式是通过ContentObserver。在CursorAdaptor中,我为每个项目定义了一个ContentObserver,并将其保存为相应视图的标记 我现在的问题是我不知道什么时候注销这些内容。我找到的唯一方法是包含活动的onDestroy(): for(int i=0;i

我有一系列文件要上传。这些内容作为条目存储在内容提供程序中。每个条目还包含上载的百分比

一个活动显示上载列表,每个文件都是一个项目,带有进度条以显示上载进度

我更新进度条的方式是通过ContentObserver。在CursorAdaptor中,我为每个项目定义了一个ContentObserver,并将其保存为相应视图的标记

我现在的问题是我不知道什么时候注销这些内容。我找到的唯一方法是包含活动的
onDestroy()

for(int i=0;i
这真的很糟糕。它在适配器和父活动之间引入了依赖关系。另一方面,未注册的ContentObserver可以防止活动被破坏,从而导致内存泄漏


你看到更好的方法了吗?

如果你有一个内容提供者,你可以用一个游标载入器代替

公共类PhotoThumbnailFragment扩展了FragmentActivity实现
LoaderManager.LoaderCallbacks{
...
}
/*
*当系统初始化加载程序和
*已准备好启动查询。这通常在初始化initLoader()时发生
*打电话来。loaderID参数包含传递给
*initLoader()调用。
*/
@凌驾
公共加载器onCreateLoader(int-loaderID,Bundle)
{
/*
*根据正在创建的加载程序的ID执行操作
*/
开关(loaderID){
案例URL\u加载程序:
//返回一个新的游标装入器
返回新游标装入器(
getActivity(),//父活动上下文
mDataUrl,//要查询的表
mProjection,//要返回的投影
null,//无选择子句
null,//没有选择参数
null//默认排序顺序
);
违约:
//传入了无效的id
返回null;
}
}

您只需定义一个游标加载器并实现回调,而不需要内容观察者。工作得更好。

您至少应该将取消注册循环移动到
onPause()
(因此,在
onResume()
)上注册它,因为您不能总是预测何时调用
onDestroy()
,或者系统是否会在不调用它的情况下终止您的应用程序。@shoe\u rat,这不是真的,这取决于您注册ContentObserver的生命周期方法。如果您在onCreate中完成注册调用时在onPause中注销,它将在多次返回该活动时爆炸(或者您需要额外检查)。另外,当应用程序被系统杀死时,你所说的是不正确的,因为如果系统杀死你,注册的ContentObserver将被系统注销(当然,否则你会一直被杀死而耗尽资源)。不要将状态与视图联系在一起,视图来来往往。注册一个接收包含所有数据的对象的观察者,将该数据更新到适配器,在adapter.S.D上调用
notifyDataSetInvalidated()
。如果正确,请只使用一个ContentObserver,不要将视图与状态信息绑定
    for (int i = 0; i < mListView.getChildCount(); i++) {
        final View v = mListView.getChildAt(i);
        final ContentObserver obs = (ContentObserver) v.getTag();
        if (obs != null) {
            getContentResolver().unregisterContentObserver(obs);
        }
    }
public class PhotoThumbnailFragment extends FragmentActivity implements
        LoaderManager.LoaderCallbacks<Cursor> {
...
}

/*
* Callback that's invoked when the system has initialized the Loader and
* is ready to start the query. This usually happens when initLoader() is
* called. The loaderID argument contains the ID value passed to the
* initLoader() call.
*/
@Override
public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle)
{
    /*
     * Takes action based on the ID of the Loader that's being created
     */
    switch (loaderID) {
        case URL_LOADER:
            // Returns a new CursorLoader
            return new CursorLoader(
                        getActivity(),   // Parent activity context
                        mDataUrl,        // Table to query
                        mProjection,     // Projection to return
                        null,            // No selection clause
                        null,            // No selection arguments
                        null             // Default sort order
        );
        default:
            // An invalid id was passed in
            return null;
    }
}