簡體   English   中英

我可以將接口傳遞給Fragment的捆綁包嗎?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM