2012-06-30 41 views
2

我遇到了這個問題,並提出了無數的帖子在這裏和其他地方涉及到這個問題。Android IllegalStateException:片段沒有附加到活動

此應用程序的目標是android 16,但min被設置爲8.所以我使用Android支持庫訪問更新的apis。

我有一個活動,加載一個是ListFragment的片段。如果以橫向模式在平板電腦上運行,則第一個片段在單擊列表項時將以2窗格佈局加載第二個片段。如果在電話上,新的活動加載第二個片段。

第二個片段使用CursorLoader訪問ContentProvider作爲其後備數據存儲。當從它自己的活動調用這個片段時,沒有問題。但是,當它處於2窗格佈局中時,CursorLoader會因上述異常而失敗。

下面是代碼:

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; 
     } 

    } 

} 

的問題發生在方法loadPrograms,具體的行:

getLoaderManager().restartLoader(0, null, this); 

這被投擲IllegalStateException異常。在仔細閱讀文檔和大量例子之後,我從來沒有看到過這個問題,爲了繼續下去而不得不被抓住。

爲了看看會發生什麼,我將代碼包裝在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是其中單對2窗格佈局被確定。監聽器在左側疼痛中的列表項被點擊時被調用。

任何人都可以解釋爲什麼這個例外發生?

該項目的完整代碼位於https://github.com/MythTV-Android/mythtv-for-android

+0

在您的代碼庫中,我沒有看到您曾在兩個窗格佈局中創建「ProgramGroupFragment」的位置。是否有創建片段的場景,但暫時不會將其附加到活動中? – CommonsWare

+0

@CommonsWare我使用調用的活動編輯了原始帖子,創建了2窗格佈局。 – dmfrey

+0

這對我來說並不明顯,爲什麼你會得到你的例外 - 抱歉。 – CommonsWare

回答

1

我經歷過類似的事情。對我來說,似乎有助於避免在使用上下文時使用ApplicationContext。嘗試創建您的ProgramCursorAdapter而不使用getApplicationContext()

相關問題