[英]Can I pass an interface to bundle of a Fragment?
由於片段需要在配置更改中生存,因此Android強烈建議在創建片段時應實現自己的newInstance()
方法,將必要的數據傳遞到其Bundle
而不要使用new MyFragment()
。
現在,問題是, 我想向此Fragment傳遞一個回調(接口) 。
最初,我嘗試使我的接口extends Serializable
,並僅使用args.putSerializable("myInterface", myInterface)
。
但是,當Android嘗試保存其狀態(將其打包)時,會引發Exception(Parcelable在編寫可序列化對象時遇到IOException)。
我知道執行此操作的官方方法是使調用方Activity實現回調,並在片段的onAttach()
期間將回調引用到該活動。
是的,它可以工作,但是感覺很奇怪,因為我實際上是在創建一個庫,現在我不是告訴用戶將回調傳遞給構建器,而是必須告訴他們您的調用者活動必須實現某個接口。
更重要的是,如果我想要的顯示此Fragment
從另一個Fragment
? onAttach()
始終附加到Activity
。
那么,有沒有一種方法可以讓用戶將回調傳遞給片段,並能夠承受配置更改(例如設備旋轉)的影響?
根據要求,這是我要傳遞的接口:
public interface OnImageSelectedListener extends Serializable {
void onImageSelected (String uri);
}
以及我如何構造此接口:
new OnImageSelectedListener() {
@Override
public void onSingleImageSelected(String uri) {
Glide.with(MainActivity.this).load(uri).into(ivImage);
}
}
您面臨此問題的原因是, Glide
是不可序列化的數據,您無法對其進行序列化。 由於序列化是Java定義並在JVM上完成的過程,因此它不了解Parcelable
,因此失敗並顯示錯誤。 即使您僅在回調方法中使用它們,這也適用。
但是,由於您正在開發庫,因此您將無法控制回調接口的使用。 因此解決方案是避免通過序列化發送該對象。
相反,當庫的用例啟動時(必須有一些入口點來觸發用例),您需要請求將引用直接傳遞給方法。 然后,您可以維護引用並在必要時執行回調。 您需要實現一些包裝器來實現它。 並通過LocalBroadcastReceiver
內部通信
如果上述方法不可行,則唯一的解決方案是讓您的圖書館用戶注冊LocalBroadcastReceive並通過廣播傳遞結果。
最后,我得出結論:
我們不應該保留回調。
假設回調函數執行以下代碼:
Glide.with(context).load(image).into(imageView);
當設備旋轉時,屬於活動或另一個片段的上述imageView也將被銷毀並重新創建。 在保留的回調中引用的舊ImageView
不再存在。
這將使Glide拋出異常; 或泄漏舊的ImageView
從而泄漏整個Activity
。
這就是為什么我們應該始終將回調引用到附加的Activity
。
如果調用者是一個Fragment
,而不是在onAttach()
中引用回調,則只需在onCreateView()
引用父片段:
if (getParentFragment() != null && getParentFragment() instanceof YourInterface) {
yourCallback = (YourInterface) getParentFragment();
}
因此,如果要回答原始問題,
我可以將接口傳遞給Fragment的捆綁包嗎?
答案可能是“否”,但您不應該這樣做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.