0

私のアクティビティでは、setScreen()メソッドを呼び出すOnClickListenerを備えた2つのCursorLoaderと2つのTextViewがあります。テキストビューをクリックすると、エラーが発生することがあります

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):

完全なコードは

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がカーソルを管理し、必要に応じて閉じる必要があることを読みました。

4

1 に答える 1

1

これがあなたの問題に関連しているかどうかはわかりませんが、次のとおりです。

  1. getSupportLoaderManager().initLoader()アダプターを作成する前に私は電話しません。うまくonLoadFinished()いくかもしれませんが、アダプターが作成される前に呼び出されると、問題が発生する可能性があるように思えます。

  2. getContentResolver().notifyChange()メソッドを呼び出すのはなぜsetScreen()ですか?私の知る限り、notifyChange()はコンテンツ プロバイダーのデータが変更されたことを通知するためのものですが、何かを変更しているようには見えません。コンテンツ プロバイダーの使用が限られているためContentResolver.notifyChange()、コンテンツ プロバイダー クラス自体の中でのみ呼び出します。例については、こちらの使用を参照してください: http://developer.android.com/resources/samples/NotePad/src/com/example/android/notepad/NotePadProvider.html

  3. これは本当に厄介ですが、onCreateLoader()おそらく次のようなことができます:

    新しい CursorLoader を返します(
    未使用の参照を作成する代わりに。

  4. 最後に、実際の質問に進むために、私がそのエラーを見たのは、閉じていない開いているカーソルがあるときだけです。CursorLoader はカーソルのライフ サイクルを処理するためgetContentResolver().query()、データベースを直接呼び出したり、クエリを実行したりして、開いているカーソルがアプリ内に他にないことを確認します。

  5. 上記のいずれも機能しない場合は、別の CursorLoader で処理しているデータを別の CursorProvider に分割できます。

于 2012-01-13T21:01:49.007 に答える