Android fragments Android IllegalStateException:未附加到活动的片段

Android fragments Android IllegalStateException:未附加到活动的片段,android-fragments,android-cursorloader,android-loader,Android Fragments,Android Cursorloader,Android Loader,我偶然发现了这个问题,并在这里和其他地方发表了许多与这个问题相关的帖子 该应用程序的目标是android 16,但min设置为8。所以我使用Android支持库来访问更新的API 我有一个活动加载一个片段,它是一个ListFragment。如果您在平板电脑上以横向模式运行,单击列表项时,第一个片段将在2窗格布局中加载第二个片段。如果在手机上,新活动将加载第二个片段 第二个片段使用游标装入器访问ContentProvider作为其备份数据存储。当这个片段从它自己的活动调用时,没有问题。但是,当它处

我偶然发现了这个问题,并在这里和其他地方发表了许多与这个问题相关的帖子

该应用程序的目标是android 16,但min设置为8。所以我使用Android支持库来访问更新的API

我有一个活动加载一个片段,它是一个ListFragment。如果您在平板电脑上以横向模式运行,单击列表项时,第一个片段将在2窗格布局中加载第二个片段。如果在手机上,新活动将加载第二个片段

第二个片段使用游标装入器访问ContentProvider作为其备份数据存储。当这个片段从它自己的活动调用时,没有问题。但是,当它处于2窗格布局时,游标加载程序将失败,出现上述异常

代码如下:

public class ProgramGroupFragment extends MythtvListFragment implements LoaderManager.LoaderCallbacks<Cursor> {

    private static final String TAG = ProgramGroupFragment.class.getSimpleName();

    private ProgramCursorAdapter adapter;

    private String programGroup = "*";

    public ProgramGroupFragment() { }

    @Override
    public Loader<Cursor> onCreateLoader( int id, Bundle args ) {

        String[] projection = { BaseColumns._ID, ProgramConstants.FIELD_TITLE, ProgramConstants.FIELD_SUB_TITLE };
        String[] selectionArgs = { programGroup };

        CursorLoader cursorLoader = new CursorLoader( getActivity(), ProgramConstants.CONTENT_URI, projection, ProgramConstants.FIELD_TITLE + "=?", selectionArgs, ProgramConstants.FIELD_SUB_TITLE );

        return cursorLoader;
    }

    @Override
    public void onLoadFinished( Loader<Cursor> loader, Cursor cursor ) {
        Log.v( TAG, "onLoadFinished : enter" );

        adapter.swapCursor( cursor );

    }

    @Override
    public void onLoaderReset( Loader<Cursor> loader ) {            
        adapter.swapCursor( null );                 
    }

    @Override
    public void onActivityCreated( Bundle savedInstanceState ) {
        super.onActivityCreated( savedInstanceState );

        adapter = new ProgramCursorAdapter(
                getActivity().getApplicationContext(), R.layout.program_row,
                null, new String[] { ProgramConstants.FIELD_SUB_TITLE }, new int[] { R.id.program_sub_title },
                CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER );

        setListAdapter( adapter );

        getLoaderManager().initLoader( 0, null, this );
    }

    public void loadPrograms( String name ) {       
        programGroup = name;
        try {
            getLoaderManager().restartLoader( 0, null, this );
        } catch( Exception e ) {
            Log.w( TAG, e.getLocalizedMessage(), e );
        }
    }

    @Override
    public void onListItemClick( ListView l, View v, int position, long id ) {    
        super.onListItemClick( l, v, position, id );

        Intent i = new Intent( getActivity(), VideoActivity.class );
        i.putExtra( VideoActivity.EXTRA_PROGRAM_KEY, id );
        startActivity( i );
    }

    private class ProgramCursorAdapter extends SimpleCursorAdapter {

        public ProgramCursorAdapter( Context context, int layout, Cursor c, String[] from, int[] to, int flags ) {
            super( context, layout, c, from, to, flags );
        }

        @Override
        public View getView( int position, View convertView, ViewGroup parent ) {

            View row =  super.getView( position, convertView, parent );

            getCursor().moveToPosition( position );
            try {
                int idIndex = getCursor().getColumnIndexOrThrow( BaseColumns._ID );
                int titleIndex = getCursor().getColumnIndexOrThrow( ProgramConstants.FIELD_TITLE );
                int subTitleIndex = getCursor().getColumnIndexOrThrow( ProgramConstants.FIELD_SUB_TITLE );

                int id = getCursor().getInt( idIndex );
                String title = getCursor().getString( titleIndex );
                String subTitle = getCursor().getString( subTitleIndex );

                if( row == null ) {
                    LayoutInflater inflater = getActivity().getLayoutInflater();

                    row = inflater.inflate( R.layout.program_row, parent, false );
                }

                TextView t = (TextView) row.findViewById( R.id.program_sub_title );
                t.setText( !"".equals( subTitle ) ? subTitle : title );

            } catch( Exception e ) {
                Log.e( TAG, "getView : error", e );
            }

            return row;
        }

    }

}
这是在抛出非法状态例外。在浏览了文档和大量示例之后,我从未见过这个问题,并且必须被抓住才能继续

我将代码包装在一个try/catch块中,只是为了看看会发生什么,令我惊讶的是,该应用程序按预期工作

编辑: 以下是建立2窗格布局的活动代码:

public class RecordingsActivity extends AbstractRecordingsActivity implements RecordingsFragment.OnProgramGroupListener {

    private static final String TAG = RecordingsActivity.class.getSimpleName();
    private static final int REFRESH_ID = Menu.FIRST + 2;

    private long requestId;
    private BroadcastReceiver requestReceiver;

    private DvrServiceHelper mDvrServiceHelper;

    @Override
    public void onCreate( Bundle savedInstanceState ) {

        super.onCreate( savedInstanceState );
        setContentView( R.layout.activity_dvr_recordings );

        RecordingsFragment recordingsFragment = (RecordingsFragment) getSupportFragmentManager().findFragmentById( R.id.fragment_dvr_program_groups );
        recordingsFragment.setOnProgramGroupListener( this );

    }

    @TargetApi( 11 )
    @Override
    public boolean onCreateOptionsMenu( Menu menu ) {
        Log.v( TAG, "onCreateOptionsMenu : enter" );

        MenuItem refresh = menu.add( Menu.NONE, REFRESH_ID, Menu.NONE, "Refresh" );
        if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
            refresh.setShowAsAction( MenuItem.SHOW_AS_ACTION_IF_ROOM );
        }

        return true;
    }

    /* (non-Javadoc)
     * @see org.mythtv.client.ui.dvr.AbstractRecordingsActivity#onOptionsItemSelected(android.view.MenuItem)
     */
    @Override
    public boolean onOptionsItemSelected( MenuItem item ) {

        switch( item.getItemId() ) {
        case REFRESH_ID:

            requestId = mDvrServiceHelper.getRecordingedList();

            return true;
        }

        return super.onOptionsItemSelected( item );
    }

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

        IntentFilter filter = new IntentFilter( DvrServiceHelper.ACTION_REQUEST_RESULT );
        requestReceiver = new BroadcastReceiver() {

            @Override
            public void onReceive( Context context, Intent intent ) {

                long resultRequestId = intent.getLongExtra( DvrServiceHelper.EXTRA_REQUEST_ID, 0 );


                if( resultRequestId == requestId ) {


                    int resultCode = intent.getIntExtra( DvrServiceHelper.EXTRA_RESULT_CODE, 0 );


                    if( resultCode == 200 ) {
                        Log.d( TAG, "Updating UI with new data" );
                    } else {
                        Log.d( TAG, "error occurred" );
                    }
                } else {
                    Log.d( TAG, "Result is NOT for our request ID" );
                }

            }
        };

        mDvrServiceHelper = DvrServiceHelper.getInstance( this );
        registerReceiver( requestReceiver, filter );
    }

    /* (non-Javadoc)
     * @see android.support.v4.app.FragmentActivity#onPause()
     */
    @Override
    public void onPause() {
        super.onPause();

        // Unregister for broadcast
        if( null != requestReceiver ) {
            try {
                unregisterReceiver( requestReceiver );
                requestReceiver = null;
            } catch( IllegalArgumentException e ) {
                Log.e( TAG, e.getLocalizedMessage(), e );
            }
        }

    }

    public void onProgramGroupSelected( String programGroup ) {
        Log.d( TAG, "onProgramGroupSelected : enter" );

        if( null != findViewById( R.id.fragment_dvr_program_group ) ) {
            FragmentManager manager = getSupportFragmentManager();

            ProgramGroupFragment programGroupFragment = (ProgramGroupFragment) manager.findFragmentById( R.id.fragment_dvr_program_group );
            FragmentTransaction transaction = manager.beginTransaction();

            if( null == programGroupFragment ) {
                Log.v( TAG, "onProgramGroupSelected : creating new programGroupFragment" );
                programGroupFragment = new ProgramGroupFragment();

                transaction
                    .add( R.id.fragment_dvr_program_group, programGroupFragment )
                    .setTransition( FragmentTransaction.TRANSIT_FRAGMENT_OPEN )
                    .addToBackStack( null )
                    .commit();
            }

            programGroupFragment.loadPrograms( programGroup );
        } else {

            Intent i = new Intent( this, ProgramGroupActivity.class );
            i.putExtra( ProgramGroupActivity.EXTRA_PROGRAM_GROUP_KEY, programGroup );
            startActivity( i );
        }

    }

}
onProgramGroupSelected的侦听器方法用于确定单个vs 2窗格布局。单击左侧列表中的列表项时,将调用侦听器

有人能解释为什么会发生这种异常吗


项目的完整代码位于

我也经历过类似的事情。对我来说,在使用上下文时避免使用
ApplicationContext
似乎有帮助。请尝试在不使用
getApplicationContext()

的情况下创建
ProgramCursorAdapter
,在代码库中,我看不到您曾经在双窗格布局中创建过
ProgramGroupFragment
。是否存在创建片段但暂时不将其附加到活动的场景?@Commonware我使用调用“建立2窗格布局”的活动编辑了原始帖子。我不清楚为什么会出现例外情况,即:抱歉。更改
CursorAdapter.FLAG\u REGISTER\u CONTENT\u OBSERVER
对于
0
@dmfrey嗨,我也遇到了类似的情况,得到了类似的异常,就像你一样,我尝试/捕捉到了它,正如你所想的,它成功了!你找到原因了吗?或者其他原因了吗?
public class RecordingsActivity extends AbstractRecordingsActivity implements RecordingsFragment.OnProgramGroupListener {

    private static final String TAG = RecordingsActivity.class.getSimpleName();
    private static final int REFRESH_ID = Menu.FIRST + 2;

    private long requestId;
    private BroadcastReceiver requestReceiver;

    private DvrServiceHelper mDvrServiceHelper;

    @Override
    public void onCreate( Bundle savedInstanceState ) {

        super.onCreate( savedInstanceState );
        setContentView( R.layout.activity_dvr_recordings );

        RecordingsFragment recordingsFragment = (RecordingsFragment) getSupportFragmentManager().findFragmentById( R.id.fragment_dvr_program_groups );
        recordingsFragment.setOnProgramGroupListener( this );

    }

    @TargetApi( 11 )
    @Override
    public boolean onCreateOptionsMenu( Menu menu ) {
        Log.v( TAG, "onCreateOptionsMenu : enter" );

        MenuItem refresh = menu.add( Menu.NONE, REFRESH_ID, Menu.NONE, "Refresh" );
        if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
            refresh.setShowAsAction( MenuItem.SHOW_AS_ACTION_IF_ROOM );
        }

        return true;
    }

    /* (non-Javadoc)
     * @see org.mythtv.client.ui.dvr.AbstractRecordingsActivity#onOptionsItemSelected(android.view.MenuItem)
     */
    @Override
    public boolean onOptionsItemSelected( MenuItem item ) {

        switch( item.getItemId() ) {
        case REFRESH_ID:

            requestId = mDvrServiceHelper.getRecordingedList();

            return true;
        }

        return super.onOptionsItemSelected( item );
    }

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

        IntentFilter filter = new IntentFilter( DvrServiceHelper.ACTION_REQUEST_RESULT );
        requestReceiver = new BroadcastReceiver() {

            @Override
            public void onReceive( Context context, Intent intent ) {

                long resultRequestId = intent.getLongExtra( DvrServiceHelper.EXTRA_REQUEST_ID, 0 );


                if( resultRequestId == requestId ) {


                    int resultCode = intent.getIntExtra( DvrServiceHelper.EXTRA_RESULT_CODE, 0 );


                    if( resultCode == 200 ) {
                        Log.d( TAG, "Updating UI with new data" );
                    } else {
                        Log.d( TAG, "error occurred" );
                    }
                } else {
                    Log.d( TAG, "Result is NOT for our request ID" );
                }

            }
        };

        mDvrServiceHelper = DvrServiceHelper.getInstance( this );
        registerReceiver( requestReceiver, filter );
    }

    /* (non-Javadoc)
     * @see android.support.v4.app.FragmentActivity#onPause()
     */
    @Override
    public void onPause() {
        super.onPause();

        // Unregister for broadcast
        if( null != requestReceiver ) {
            try {
                unregisterReceiver( requestReceiver );
                requestReceiver = null;
            } catch( IllegalArgumentException e ) {
                Log.e( TAG, e.getLocalizedMessage(), e );
            }
        }

    }

    public void onProgramGroupSelected( String programGroup ) {
        Log.d( TAG, "onProgramGroupSelected : enter" );

        if( null != findViewById( R.id.fragment_dvr_program_group ) ) {
            FragmentManager manager = getSupportFragmentManager();

            ProgramGroupFragment programGroupFragment = (ProgramGroupFragment) manager.findFragmentById( R.id.fragment_dvr_program_group );
            FragmentTransaction transaction = manager.beginTransaction();

            if( null == programGroupFragment ) {
                Log.v( TAG, "onProgramGroupSelected : creating new programGroupFragment" );
                programGroupFragment = new ProgramGroupFragment();

                transaction
                    .add( R.id.fragment_dvr_program_group, programGroupFragment )
                    .setTransition( FragmentTransaction.TRANSIT_FRAGMENT_OPEN )
                    .addToBackStack( null )
                    .commit();
            }

            programGroupFragment.loadPrograms( programGroup );
        } else {

            Intent i = new Intent( this, ProgramGroupActivity.class );
            i.putExtra( ProgramGroupActivity.EXTRA_PROGRAM_GROUP_KEY, programGroup );
            startActivity( i );
        }

    }

}