2012-11-26 34 views
2

Eclipse生成的主細節流在延伸ListFragment的類中有一些回調魔術 - 我說魔術是因爲這就是當你是Android和Java noob時,看起來像是什麼:)在主細節流程中回調'魔術'

考慮下面的代碼有人可以回答我幾個問題:

  1. 什麼是ListFragmentonAttach方法做mCallbacks = (Callbacks) activity
  2. onItemSelected方法調用onListItemClick方法ListFragment,需要執行的方法還是onItemSelectedFragmentActivity
  3. 所有這些onItemSelected方法需要id類型String(因爲DummyContentidString)。如果我將DummyContentid更改爲long,那麼我需要更改哪些onItemSelected方法?我試圖改變一個在FragmentActivity但這@Override所以我不能:(

謝謝

public class RecordingListFragment extends ListFragment { 

    private static final String STATE_ACTIVATED_POSITION = "activated_position"; 

    private Callbacks mCallbacks = sDummyCallbacks; 
    private int mActivatedPosition = ListView.INVALID_POSITION; 

    public interface Callbacks { 

     public void onItemSelected(String id); 
    } 

    private static Callbacks sDummyCallbacks = new Callbacks() { 
     @Override 
     // NEEDS IMPLEMENTATION - i guess???? 
     public void onItemSelected(String id) { 
     } 
    }; 

... 

    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     if (!(activity instanceof Callbacks)) { 
      throw new IllegalStateException("Activity must implement fragment's callbacks."); 
     } 

     mCallbacks = (Callbacks) activity; 
    } 

    @Override 
    public void onDetach() { 
     super.onDetach(); 
     mCallbacks = sDummyCallbacks; 
    } 

    @Override 
    public void onListItemClick(ListView listView, View view, int position, long id) { 
     super.onListItemClick(listView, view, position, id); 
     mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id); 
    } 

... 

} 

還有一檔...

public class RecordingListActivity extends FragmentActivity 
     implements RecordingListFragment.Callbacks { 

    private boolean mTwoPane; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_recording_list); 
     getActionBar().setDisplayHomeAsUpEnabled(true); 

     if (findViewById(R.id.recording_detail_container) != null) { 
      mTwoPane = true; 
      ((RecordingListFragment) getSupportFragmentManager() 
        .findFragmentById(R.id.recording_list)) 
        .setActivateOnItemClick(true); 
     } 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     switch (item.getItemId()) { 
      case android.R.id.home: 
       NavUtils.navigateUpFromSameTask(this); 
       return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 

    @Override 
    public void onItemSelected(String id) { 
     if (mTwoPane) { 
      Bundle arguments = new Bundle(); 
      arguments.putString(RecordingDetailFragment.ARG_ITEM_ID, id); 
      RecordingDetailFragment fragment = new RecordingDetailFragment(); 
      fragment.setArguments(arguments); 
      getSupportFragmentManager().beginTransaction() 
        .replace(R.id.recording_detail_container, fragment) 
        .commit(); 

     } else { 
      Intent detailIntent = new Intent(this, RecordingDetailActivity.class); 
      detailIntent.putExtra(RecordingDetailFragment.ARG_ITEM_ID, id); 
      startActivity(detailIntent); 
     } 
    } 
} 

回答

4

ListCragment的onAttach方法與mCallbacks = (回調)活動有什麼關係?

onAttach回調的Activity/FragmentActivity(賦予了Fragment將被捆綁/使用)被傳遞到Fragment實例(通過活性參數)。該行簡單地將Activity轉換爲Callbacks接口,以便稍後在Fragment(參見下文)中使用。您的Activity必須實現該接口,否則代碼將由於以前的if條件而失敗。基本上,onAttach方法中的代碼表示:「將使用此片段的活動必須實現Callbacks接口,否則代碼將失敗,並出現IllegalStateException」

其中onItemSelected方法 ListFragment,需要執行或 FragmentActivity onItemSelected的一個onListItemClick方法被調用?

在非常原始的解釋:本RecordingListFragment保持一個引用(mCallbacks字段)向Callbacks類型的對象(意味着它實現了Callbacks接口的類)。最初,這個Callabacks參考代碼將指定一個默認/空Callbacks參考(sDummyCallbacks),它不會做任何事情(所以沒有,你沒有提供的sDummyCallbacks一些實現)作爲其onItemSelected是爲空,這是爲了避免在某些情況下可能的NullPointerException(例如,如果您不指定mCallbacks字段中的內容,並且您打電話給onItemSelected)。當onAttach方法運行時,參考Activity將存在此Fragment將轉換爲Callbaks並放入mCallbacks字段。發生這種情況後,當您撥打mCallbacks.onItemSelected()時,將會調用FragmentActivityonItemSelected方法,並運行該方法的代碼。如果稍後調用onDetach,則mCallbacks將再次指向sDummyCallbacks,發生此情況後,調用mCallbacks.onItemSelected()將不會執行任何操作。

上述接口系統非常重要,因爲它將使您的RecordingListFragment成爲您的代碼中更具可重用性的組件,因爲它不會綁定到特定的Activity實現。當用戶點擊片段列表中的某個項目時,您將調用mCallbacks引用上的onItemSelected以從該對象(您的案例中的活動)運行onItemSelected方法。你的片段不知道如何實現接口,它甚至不關心。想一想,例如您有三項活動,每項活動都使用RecordingListFragment片段。您需要如何更改RecordingListFragment類,才能使用它將使用的三個活動?

所有這些onItemSelected方法都採用String類型的ID(因爲 DummyContent id是一個String)。如果我將DummyContent id更改爲long, 哪些onItemSelected方法需要更改?我試圖改變 一個在FragmentActivity但這@Override所以我不允許 以:(

修改界面:

public interface Callbacks { 

     public void onItemSelected(long id); 
} 

如果您保存Java文件,Eclipse會抱怨(你必須覆蓋一個超類方法),其中這個接口來實現對於sDummyCallbacks

private static Callbacks sDummyCallbacks = new Callbacks() { 
    @Override 
    // NEEDS IMPLEMENTATION - i guess???? <- it doesn't need no implementation 
    // it's purpose is to do nothing 
    public void onItemSelected(long id) { 
    } 
}; 

另外,FragmentActivity IMPL對此語句的Callbacks接口,所以你需要改變它:

public class RecordingListActivity extends FragmentActivity 
     implements RecordingListFragment.Callbacks { 

    @Override 
    public void onItemSelected(long id) { 
     if (mTwoPane) { 
    // ... 

最後你會在你的片段使用mCallbacks

@Override 
public void onListItemClick(ListView listView, View view, int position, long id) {  
    mCallbacks.onItemSelected(id); 
} 

我建議你花一些時間來研究了一下有關java語言,所以你將努力理解Android代碼,而不是Android代碼+ java方式。