2013-11-15 90 views
8

我開始之前,我有過的問題看,如之間的物體:安卓:傳遞片段

Passing data between fragments: screen overlap How to pass values between Fragments

以及Android的文檔:

http://developer.android.com/training/basics/fragments/communicating.html

以及這篇文章:

http://manishkpr.webheavens.com/android-passing-data-between-fragments/

雖然上面提到的所有情況都與我的相似,但並不完全相同。我跟着一個很好的教程在這裏(我的代碼有些部分是基於這篇文章):

http://www.androidhive.info/2013/10/android-tab-layout-with-swipeable-views-1/

我有以下文件:

RegisterActivity.java
NonSwipeableViewPager.java
ScreenSliderAdapter .java
RegisterOneFragment.java
RegisterTwoFragment.java

而以下佈局:

activity_register.xml
fragment_register_one.xml
fragment_register_two.xml

什麼,我想實現的是傳遞一個序列化對象從RegisterFragmentOne到RegisterFragmentTwo。

到目前爲止,這是我做了什麼(一些代碼省略):

RegisterActivity.java

public class RegisterActivity extends FragmentActivity 
      implements RegisterOneFragment.OnEmailRegisteredListener{ 

    public static NonSwipeableViewPager viewPager; 
    private ScreenSliderAdapter mAdapter; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_register); 

     // Initilization 
     mAdapter = new ScreenSliderAdapter(getSupportFragmentManager()); 
     viewPager = (NonSwipeableViewPager) findViewById(R.id.pager); 
     viewPager.setAdapter(mAdapter); 
    } 

    public void onEmailRegistered(int position, Registration regData){ 
     Bundle args = new Bundle(); 
     args.putSerializable("regData", regData); 
     viewPager.setCurrentItem(position, true); 
    } 
} 

ScreenSliderAdapter.java

public class ScreenSliderAdapter extends FragmentPagerAdapter{ 

    public ScreenSliderAdapter(FragmentManager fm) { 
     super(fm); 
    } 

    @Override 
    public Fragment getItem(int index) { 

     switch (index) { 
     case 0: 
      return new RegisterOneFragment(); 
     case 1: 
      return new RegisterTwoFragment(); 
     case 2: 
      return new RegisterThreeFragment(); 
     } 

     return null; 
    } 

    @Override 
    public int getCount() { 
     return 3; 
    } 
} 

NonSwipeableViewPager。 java(擴展ViewPager類,並覆蓋以下)

@Override 
public boolean onInterceptTouchEvent(MotionEvent arg0) { 
    // Never allow swiping to switch between pages 
    return false; 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    // Never allow swiping to switch between pages 
    return false; 
} 

RegisterOneFragment.java

public class RegisterOneFragment extends Fragment { 
    OnEmailRegisteredListener mCallBack; 
    public interface OnEmailRegisteredListener { 
     /** Called by RegisterOneFragment when an email is registered */ 
     public void onEmailRegistered(int position, Registration regData); 
    } 

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 { 
     mCallBack = (OnEmailRegisteredListener) activity; 
    } catch (ClassCastException e) { 
     throw new ClassCastException(activity.toString() 
       + " must implement OnEmailRegisteredListener"); 
    } 
} 

... And some to execute some HTTP request via separate thread... 
} 

我試圖做到的是,當永遠的用戶按下上RegisterOneFragment按鈕,數據將被髮送到服務器(並通過JSON返回一些驗證)。如果返回的數據有效,應用程序應該轉到下一個RegistrationTwoFragment片段。

我對如何在片段之間傳遞對象感到困惑,因爲我的片段是使用Adapter創建的。然後,該適配器被附加到我的活動。

任何人都可以幫助我嗎? THX

編輯1:

我試圖建立一個快捷方式(可惜不工作),像這樣:

在RegisterActivity我創建:

public Registration regData; 

和RegisterOneFragment:

/* PLACED ON POST EXECUTE */ 
((RegisterActivity)getActivity()).regData = regData; 

Finall Ÿ稱它在RegisterTwoFragment

Registration regData; 
regData = ((RegisterActivity) getActivity()).regData; 

它拋出一個NullPointerException異常

編輯2

只是要清楚,RegisterActivty包含多個片段。用戶可以在片段之間導航的唯一方法是單擊按鈕。該活動沒有選項卡欄。

+0

你可以告訴http://stackoverflow.com/questions/40126867/how-to-access-custom-arraylist-in-fragment – albert

回答

3

我通常會在包含活動中使用與此類似的setter或方法。

所以,如果我理解正確的話,你希望用戶訪問​​,然後完成後,使用這些數據,驗證它,如果有效,把它傳遞給RegistrationTwoFragment和用戶移動到這個Fragment

您是否可以簡單地在您的onEmailRegistered方法中調用validateJson(regData)來處理活動中的驗證,如果成功,則將事務提交到RegistrationTwoFragment

然後,您只需要在您的活動或片段中指定getRegistrationOneData()中的活動或setData(Registration args)片段中的獲取者和設置者,如上面的示例所示。

我不知道有什麼辦法可以直接將參數傳遞給片段。

+0

是的,這正是我試圖做我的代碼。參考您的解決方案,這是否意味着我不必使用適配器?同時我會盡量遵循你的建議。 Thx ... – Jeremy

+0

如果你想保留尋呼機和適配器,那麼你應該保留它,但我認爲你也可以用supportFragmentManager()和事務處理它。 – sturrockad

+0

我想你是對的,只是我試圖用盡可能少的努力完成這項工作...... – Jeremy

1

我找到了解決我的問題,我確信不這樣做的正確方法...

所以在RegisterActivity.java我添加+修正以下行(感謝@sturrockad):

public Registration getRegistrationData(){ 
    return this.regData; 
} 

public void onEmailRegistered(int position, Registration regData){ 
    this.regData = regData; 
    viewPager.setCurrentItem(position, true); 
} 

然後在RegisterTwoFragments.java(或片段,我想接收對象):

public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 

    View rootView = inflater.inflate(R.layout.fragment_register_two, container, false); 
    regData = ((RegisterActivity) getActivity()).getRegistrationData(); 
    ... 
+0

很高興爲您提供幫助。如果您對get()方法解決方案感到滿意,請接受答案。 – sturrockad

8

這很容易通過實現Serializable接口來分享你的對象自定義對象。我寫了一篇關於這個here的教程。

從片段的一種:

android.support.v4.app.FragmentTransaction ft = 
    getActivity().getSupportFragmentManager().beginTransaction(); 
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); 
OfficeCategoryFragment frag = new OfficeCategoryFragment(); 

Bundle bundles = new Bundle(); 
Division aDivision = divisionList.get(position); 

// ensure your object has not null 
if (aDivision != null) { 
    bundles.putSerializable("aDivision", aDivision); 
    Log.e("aDivision", "is valid"); 
} else { 
    Log.e("aDivision", "is null"); 
} 
frag.setArguments(bundles); 
ft.replace(android.R.id.content, frag); 
ft.addToBackStack(null); 
ft.commit(); 

在片段2:

Bundle bundle = getArguments(); 
Division division= (Division) bundle.getSerializable("aDivision"); 
Log.e("division TEST", "" + division.getName()); 
+0

對於有人試圖用較少的努力做類似的事情:使用谷歌gson序列化你的POJO到JSON併發送捆綁。它更好,因爲你不需要爲每個對象實現可序列化,並且當你改變對象屬性(在你的後端)時,你不需要改變可序列化的實現。 – sagits

0

我用於設置與Pacelable或序列化轉移對象,但每當我添加其他變量到對象(模型),我必須全部註冊。這很不方便。

在活動或片段之間傳輸對象非常容易。

Android DataCache

  1. 把你的數據對象KimchiDataCache比如在你的活動或片段。

    User userItem = new User(1, "KimKevin"); // Sample Model 
    
    KimchiDataCache.getInstance().put(userItem); 
    
    // add your activity or fragment 
    
  2. 讓您的數據對象在您添加片段的活性。

    public class MainFragment extends Fragment{ 
        private User userItem; 
    
        @Override 
        public void onCreate(Bundle savedInstanceState) { 
         super.onCreate(savedInstanceState); 
    
         userItem = KimchiDataCache.getInstance().get(User.class); 
        } 
    
+1

這是單態模式的表現,這是一個反模式,它的單元測試的痛苦。 –

+0

對於有人試圖用較少的努力做類似的事情:使用谷歌gson序列化您的POJO到JSON併發送它與捆綁(setArguments)。 – sagits