2013-07-03 181 views
9

我有一個Activity與多個Fragment s。我想顯示或從Fragment之一開放另一個Fragment。我知道一個Activity應該是開放Fragment s的任務,所以我嘗試了幾件事情。活動和片段互動

FIRST
我試圖用getActivity()並投它,所以我可以調用Activity的方法來顯示Fragment然而,這會在Fragment依賴與Activity,我想避免添加依賴如果可能的話。

第二
接下來,我嘗試了聽衆通知Activity它應該表現出Fragment。所以我在Activity中創建了一個類來實現監聽器接口。但是我遇到了問題,因爲我不得不使用New MyActivity().new Listener();,並且當我嘗試使用getSupportFragmentManager()時它會拋出Exception,因爲Activity的這個實例未初始化。

第三
我又試圖有Activity直接實現監聽器的工作原理,因爲那時我只創建與聽衆,而不是活動的依賴性。但是現在我已經到了我的Activity將實施2 - 4個不同的界面,這使我猶豫不決,因爲它會嚴重降低凝聚力。

因此,我試過的任何方式似乎都跑進了一堵磚牆,並創建依賴關係,我不知道我需要創建。我是否搞砸了,不得不採取其中一種選擇?如果是的話哪個選項最好?任何幫助或建議是非常感謝。

+0

有很多方法可以做到這一點,我喜歡儘可能的去耦合,爲此我喜歡一個事件總線。請參閱otto,例如:http://square.github.io/otto/。 (讓你擺脫所有的界面/監聽器,傳遞數據,用強大的類型來做,用簡潔明瞭的方式來做。) –

+0

它看起來很有希望。我必須檢查一下。謝謝你的提示。 –

回答

10

就我個人而言,我會說片段應該被認爲是可重用和模塊化的組件。所以爲了提供這種可重用性,片段不應該太瞭解他們的父母活動。但是作爲回報,活動必須知道他們持有的片段。

因此,我認爲第一個選項不應該被視爲您提到的依賴性原因,從而導致高度耦合的代碼。

關於第二個選項,片段可以委託任何應用程序流或UI相關決策(顯示新片段,決定在片段特定事件觸發時要執行什麼操作等)。所以你的聽衆/回調應該是特定於片段的,因此他們應該被分段聲明。持有這些片段的活動應該實現這些接口並決定要做什麼。

因此,對我來說,第三種選擇更有意義。我相信活動在具體回調方面持有和執行的內容更具可讀性。但是,你是對的,你的活動可能會成爲上帝的對象。

也許你可以檢查Square的Otto項目,如果你不想實現幾個接口。這基本上是一個事件公共汽車。

+0

感謝您和@Charlie Collins將我指向Otto圖書館。這看起來非常有希望,似乎它會完成我期待的。感謝大家的幫助。 –

3

我認爲你的第二個選擇是在正確的軌道上。

在你的片段,定義了監聽器接口:

class MyFragment ... 
{ 
    public interface IMyFragmentListenerInterface 
    { 
     void DoSomething(); 
    } 
} 

有活動實現的接口:

class MyActivity 
{ 
    class MyListener1 implements IMyFragmentListenerInterface { ... } 
} 

傳遞到聽者的片段。我喜歡在Fragment的構造函數中完成它,但只有當你完全由你自己管理片段時纔有效。相反,您可以將setListener方法添加到片段中。

+3

「setListener」方法存在問題:如果操作系統銷燬並重新創建了片段(使用默認的空白構造函數),則對該偵聽器的引用將丟失。實現這一目標的最好方法是將代碼放入'onAttach'方法中,將片段的父活動連接爲偵聽器,並在運行時檢查它是否支持所需的接口。請參閱http://developer.android.com/guide/components/fragments.html:'創建活動回調到活動'。 –

0

你有沒有嘗試過這樣的事情(從片段):

FragmentTransaction ft = 
    getActivity().getSupportFragmentManager().beginTransaction(); 
Fragment prev = 
    getActivity().getSupportFragmentManager().findFragmentByTag("some_name"); 
if (prev != null) { 
    ft.remove(prev); 
} 
ft.addToBackStack(null); 

DialogFragment dialogFragment = DialogFragmentClass.newInstance(); 
dialogFragment.show(ft, "some_name"); 

讓我知道,歡呼聲。

2

您需要將您的數據從Fragment X傳遞到您的FragmentActivity,這會將此數據傳遞到您的Fragment Y.您通過在您的fragment類中定義的接口來實現此目的,並實例化一個在onAttach()。如何做到這一點這裏 Communication With other Fragments

簡單的例子

更多信息,可以考慮片段A和片段B片段A是列表片段,每當一個項目被選中它會有什麼變化顯示在片段B.很簡單,對嗎?

首先,定義片段A.

public class FragmentA extends ListFragment{ 

    //onCreateView blah blah blah 

} 

而這裏的片段B

public class FragmentB extends Fragment{ 

//onCreateView blah blah blah 

} 

這是我的FragmentActivity將統治他們都

public class MainActivity extends FragmentActivity{ 

//onCreate 
//set up your fragments 

} 

想必你有這樣的事情已經,現在這裏是你將如何改變FragmentA(我們需要從中獲取一些數據的列表片段)。

public class FragmentA extends ListFragment implements onListItemSelectedListener, onItemClickListener{ 

OnListItemSelectedListener mListener; 

    //onCreateView blah blah blah 



// Container Activity must implement this interface 
    public interface OnListItemSelectedListener { 
    public void onListItemSelected(int position); 
} 


} 


    @Override 
    public void onAttach(Activity activity) { 
    super.onAttach(activity); 

    // This makes sure that the container activity has implemented 
    // the callback interface. If not, it throws an exception 
    try { 
     mListener = (OnListItemSelectedListener) activity; 
    } catch (ClassCastException e) { 
     throw new ClassCastException(activity.toString() 
       + " must implement OnListItemSelectedListener"); 
    } 
} 


    @Override 
public void onItemClick(AdapterView<?> parent, View view, int position, long id){ 


//Here's where you would get the position of the item selected in the list, and pass that position(and whatever other data you need to) up to the activity 
//by way of the interface you defined in onAttach 

    mListener.onListItemSelected(position); 


} 

這裏最重要的考慮是你的父Activity實現了這個接口,否則你會得到一個異常。如果成功實施,每次選擇列表片段中的項目時,您的活動都會被通知其位置。很明顯,你可以用任何數量或類型的參數來改變你的接口,在這個例子中,我們只是傳入整數位置。希望這個澄清一個人,祝你好運。

0

爲了獲得鬆散耦合的最大值,您可以使用GreenRobot的Square或EventBus中的OTTO等事件總線。 您的片段可以觸發由您的活動處理的事件,反之亦然。關於這一點很酷的是組件(活動,片段)對彼此沒有任何影響,你不需要聲明任何接口或回調。

我在我所有的項目中都使用它,它性能穩定,對性能影響很小(在正常情況下)。

2

創建界面

public interface ListenFromActivity { 
    void doSomethingInFragment(); 
} 

Activity類保持ListenFromActivity接口refrence

public ListenFromActivity activityListener; 

張揚方法來設置監聽

public void setActivityListener(ListenFromActivity activityListener) { 
     this.activityListener = activityListener; 
    } 

添加一些觸發點在活動課, H趁着我已經使用的用戶交互

@Override 
    public void onUserInteraction() { 
     super.onUserInteraction(); 

     if (null != activityListener) { 
      activityListener.doSomethingInFragment(); 
     } 
    } 

現在片段類

讓你的片段實現接口類

public class SomeFragment extends Fragment implements ListenFromActivity 

的Android工作室將提示您實現接口的方法在片段

void doSomethingInFragment() 
{//Add your code here 
} 

最後部部分聽者實例類似這樣的活性片段onCreate方法

((ListnerActivity) getActivity()).setActivityListener(SomeFragment.this); 

DONE !!。現在您可以從活動中調用片段方法。