2013-02-01 129 views
54

我最近厭倦了不斷地必須知道String鍵來在創建我的Fragments時將參數傳入Bundles。所以我決定爲我的Fragments製作構造函數,這些構造函數將採用我想要設置的參數,並將這些變量放入Bundles中,使用正確的String鍵,因此不需要其他FragmentsActivities需要知道這些鍵。創建片段:構造函數vs newInstance()

public ImageRotatorFragment() { 
    super(); 
    Log.v(TAG, "ImageRotatorFragment()"); 
} 

public ImageRotatorFragment(int imageResourceId) { 
    Log.v(TAG, "ImageRotatorFragment(int imageResourceId)"); 

    // Get arguments passed in, if any 
    Bundle args = getArguments(); 
    if (args == null) { 
     args = new Bundle(); 
    } 
    // Add parameters to the argument bundle 
    args.putInt(KEY_ARG_IMAGE_RES_ID, imageResourceId); 
    setArguments(args); 
} 

然後我拿出像正常的參數。

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    Log.v(TAG, "onCreate"); 

    // Set incoming parameters 
    Bundle args = getArguments(); 
    if (args != null) { 
     mImageResourceId = args.getInt(KEY_ARG_IMAGE_RES_ID, StaticData.getImageIds()[0]); 
    } 
    else { 
     // Default image resource to the first image 
     mImageResourceId = StaticData.getImageIds()[0]; 
    } 
} 

然而,林特採取了問題這一點,他說不要有與其他參數的構造函數的Fragment子類,我需要使用@SuppressLint("ValidFragment"),即使運行應用程序。事情是,這段代碼工作得很好。我可以使用ImageRotatorFragment(int imageResourceId)或舊學校方法ImageRotatorFragment()並手動調用setArguments()。當Android需要重新創建片段(方向更改或內存不足)時,它會調用ImageRotatorFragment()構造函數,然後將相同的參數Bundle與我的值一起傳遞,該值將被正確設置。

所以我一直在尋找「建議」的方法,並看到很多使用newInstance()來創建帶參數的Fragments的示例,這些參數似乎與我的構造函數完成相同的事情。所以我做了我自己的測試,它和以前一樣完美無瑕,減去了Lint對它的嗚嗚聲。

public static ImageRotatorFragment newInstance(int imageResourceId) { 
    Log.v(TAG, "newInstance(int imageResourceId)"); 

    ImageRotatorFragment imageRotatorFragment = new ImageRotatorFragment(); 

    // Get arguments passed in, if any 
    Bundle args = imageRotatorFragment.getArguments(); 
    if (args == null) { 
     args = new Bundle(); 
    } 
    // Add parameters to the argument bundle 
    args.putInt(KEY_ARG_IMAGE_RES_ID, imageResourceId); 
    imageRotatorFragment.setArguments(args); 

    return imageRotatorFragment; 
} 

我個人認爲使用構造是一個更普遍的做法比知道使用newInstance()和傳遞參數。我相信你可以在Activities和Lint中使用相同的構造函數技巧,而不會抱怨它。 所以基本上我的問題是,爲什麼谷歌不希望你使用參數爲Fragments的構造函數?

我唯一的猜測是所以你不要試圖設置一個實例變量,而不使用Bundle,當Fragment被重新創建時它不會被設置。通過使用static newInstance()方法,編譯器不會讓您訪問實例變量。

public ImageRotatorFragment(int imageResourceId) { 
    Log.v(TAG, "ImageRotatorFragment(int imageResourceId)"); 

    mImageResourceId = imageResourceId; 
} 

我仍然不覺得這是足夠的理由不允許在構造函數中使用參數。任何人都有這方面的見解?

回答

59

我個人發現使用構造函數比知道使用newInstance()和傳遞參數更加普遍。

factory method pattern在現代軟件開發中使用相當頻繁。

所以基本上我的問題是,爲什麼谷歌不希望你使用碎片參數的構造函數?

你回答了自己的問題:

我唯一的猜測是,所以你不要嘗試設置一個實例變量不使用捆綁,這不會得到當片段被重新設置。

正確。

我仍然不覺得這是足夠的理由不允許在構造函數中使用參數。

歡迎您的意見。歡迎您以每個構造函數或每個工作區的方式禁用此Lint檢查。

0

Android只會使用默認的構造函數重新創建它殺死的碎片,因此我們在其他構造函數中執行的任何初始化都將丟失。因此數據將會丟失。