CursorLoader和完成光标尚未停用或封闭的错误 [英] CursorLoader and Finalizing cursor that has not been deactivated or closed error

查看:178
本文介绍了CursorLoader和完成光标尚未停用或封闭的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的活动我有2 CursorLoader和2 TextView的一个OnClickListener调用setScreen()方法。点击Textviews有时我有误差

In my activity I have 2 CursorLoader and 2 TextView with a OnClickListener that calls the setScreen() method. Clicking the Textviews sometimes I have the error

11-29 15:27:26.045: INFO/dalvikvm(1223): Ljava/lang/IllegalStateException;: Finalizing cursor android.database.sqlite.SQLiteCursor@43c02e18 on MAIN_TABLE that has not been deactivated or closed
11-29 15:27:26.045: INFO/dalvikvm(1223):     at android.database.sqlite.SQLiteCursor.finalize(SQLiteCursor.java:596)
11-29 15:27:26.045: INFO/dalvikvm(1223):     at dalvik.system.NativeStart.run(Native Method)
11-29 15:27:26.065: INFO/dalvikvm(1223): Uncaught exception thrown by finalizer (will be discarded):

完整的code是

The complete code is

public class ActivityMatchesList extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor> {
    private MyAdapter1 mAdapter1;
    private MyAdapter2 mAdapter2;
    private int mTab;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /** Cursor Loader */
        getSupportLoaderManager().initLoader(1, null, this);
        getSupportLoaderManager().initLoader(2, null, this);
        /** set content view */
        setContentView(R.layout.main_list);
        View vv = new View(this);
        LinearLayout ll = (LinearLayout) findViewById(R.id.boxRanking);
        vv = View.inflate(this, R.layout.tab_ranking, null);
        ll.addView(vv, new LinearLayout.LayoutParams(ll.getLayoutParams().width, ll.getLayoutParams().height));
        /** set colors */
        ListView lvLive = (ListView)findViewById(R.id.matchListList);
        ListView lvLeagueMatches = (ListView) findViewById(R.id.listLeagueMatches);
        /** create and set Adapters */
        mAdapter1 =     new MyAdapter1(
            this, 
            R.layout.main_list_row, 
            null,
            0);
        mAdapter2 = new MyAdapter2(
            this, 
            R.layout.list_ran_row, 
            null,
            0);
        lvLive.setAdapter(mAdapter1);
        lvLeagueMatches.setAdapter(mAdapter2);          

        /** listener */
        TextView tabLive = (TextView) findViewById(R.id.tab_main);
        TextView tabRank = (TextView) findViewById(R.id.tab_ran);
        tabLive.setOnClickListener(onClickListenerTab);
        tabRank.setOnClickListener(onClickListenerTab);
    }

    @Override
    protected void onResume() {
        super.onResume();
        setScreen();
    }

    private void setScreen() {
        if (mTab!=Constants.Tab.TAB_2) mTab=Constants.Tab.TAB_1;
        LinearLayout llRanking = (LinearLayout) findViewById(R.id.boxRanking);
        ListView lvLive = (ListView)findViewById(R.id.matchListList);
        switch (mTab){
            case Constants.Tab.TAB_1:
                llRanking.setVisibility(View.GONE);
                lvLive.setVisibility(View.VISIBLE);
                break;
            case Constants.Tab.TAB_2:
                llRanking.setVisibility(View.VISIBLE);
                lvLive.setVisibility(View.GONE);
                break;  
        }
        getContentResolver().notifyChange(MyProvider.CONTENT_URI, null);
    }

    private OnClickListener onClickListenerTab = new OnClickListener() {
        public void onClick(final View v) {
            int mNewTab;
            if(v.getId()==R.id.tab_ran){
                mNewTab = Constants.Tab.TAB_2;
            } else {
                mNewTab = Constants.Tab.TAB_1;
            } 
            if (mTab != mNewTab) {
                mTab = mNewTab;
                setScreen();
            }
        }
    };

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        switch (id){
        case 1:
            CursorLoader cursorLoaderLive = new CursorLoader(
                this, 
                MyProvider.CONTENT_URI_MAIN, 
                null, 
                null, 
                null, 
                "MatchDateYear, MatchDateMonth, MatchDateDay, MatchHour, MatchMinute");
            return cursorLoaderLive;
        case 2:
            CursorLoader cursorLoaderRankingLeague = new CursorLoader(
                this, 
                MyProvider.CONTENT_URI_RAN, 
                null, 
                "Round=3 AND IsMatch=1", 
                null, 
                null);
            return cursorLoaderRankingLeague;
        default:
            return null;
        }
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        switch (loader.getId()){
        case 1:
            mAdapter1.swapCursor(cursor);
            break;
        case 2:
            mAdapter2.swapCursor(cursor);
            break;
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        switch (loader.getId()){
        case 1:
            mAdapter1.swapCursor(null);
            break;
        case 2:
            mAdapter2.swapCursor(null);
            break;
        }
    }
}

为什么CursorLoader给出了这样的错误?我读了CursorLoader应该管理光标并关闭它在必要时。

Why CursorLoader gives this error? I read that CursorLoader should manage the cursor and close it when necessary.

推荐答案

不知道任何这是关系到你的问题,但在这里有云:

Not sure if any of this is related to your problem, but here goes:

  1. 我不会把 getSupportLoaderManager()。initLoader()在创建适配器之前。也许它的工作原理,但如果 onLoadFinished()被称为在创建适配器之前,在我看来,像它可能导致的问题。

  1. I wouldn't call getSupportLoaderManager().initLoader() before you create your adapters. Maybe it works, but if onLoadFinished() gets called before the adapters are created, it seems to me like it could cause issues.

为什么你叫 getContentResolver()。有NotifyChange() setScreen()的方法?据我了解,<一个href="http://developer.android.com/reference/android/content/ContentResolver.html#notifyChange%28android.net.Uri,%20android.database.ContentObserver%29"相对=nofollow>有NotifyChange()是,在内容提供商的数据已经改变的通知,但它不看我像你改变任何东西。从我有限的使用内容提供商,我只叫 ContentResolver.notifyChange()内容提供商类本身。见它的使用这里的一个例子:<一href="http://developer.android.com/resources/samples/NotePad/src/com/example/android/notepad/NotePadProvider.html" rel="nofollow">http://developer.android.com/resources/samples/NotePad/src/com/example/android/notepad/NotePadProvider.html

Why are you calling getContentResolver().notifyChange() in your setScreen() method? As far as I understand, notifyChange() is for notification that data in the content provider has changed, but it doesn't look to me like you're changing anything. From my limited use of content providers, I only call ContentResolver.notifyChange() within the content provider class itself. See its use here for an example: http://developer.android.com/resources/samples/NotePad/src/com/example/android/notepad/NotePadProvider.html

这是真的很挑剔,但在 onCreateLoader()你很可能做这样的事情:

This is really nitpicky, but in onCreateLoader() you could probably do something like this:

return new CursorLoader(

而不是创建未使用的引用。

instead of creating unused references.

最后,为了获得实际的问题,我已经看到了这个错误的唯一的一次是当我有一个打开的游标,我还没有关闭。由于CursorLoader处理光标生命周期,我想看看,以确保没有其他地方在你的应用程序,你来自哪里调用 getContentResolver()有一个打开的游标,等等。查询()或直接查询数据库。

Lastly, to get to the actual question, the only time I've seen that error is when I have an open cursor that I haven't closed. Since CursorLoader handles the cursor life cycle, I'd look to make sure there isn't anywhere else in your app where you have an open cursor, like from calling getContentResolver().query() or querying a database directly.

如果以上都没有效果的,也许你可以分割你处理有独立CursorLoaders成单独CursorProviders数据。

If none of the above works, maybe you could split the data you're handling with separate CursorLoaders into separate CursorProviders.

这篇关于CursorLoader和完成光标尚未停用或封闭的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆