2013-12-20 58 views
2

我有一個mainActivity我從哪裏調用片段列表。如何只加載一次碎片並保存其狀態?

現在,在此列表中,我有一個名爲MyAccount的片段,它使用webservice顯示Account Details的列表。

我想要的是我只想加載myAccount細節一次(第一次)片段加載,而不是每一次(這是現在正在發生的)。此外,我想在操作欄中設置一個刷新按鈕,所以點擊該刷新按鈕/圖像,帳戶詳情將被加載並顯示。

這是我實現::

getFragement()在主Acitivty ::

private List<Fragment> getFragments() 
    { 
     List<Fragment> fList = new ArrayList<Fragment>(); 


      fList.add(Fragment.instantiate(this,Fragment1.class.getName())); 


      fList.add(Fragment.instantiate(this,Fragment2.class.getName())); 



      fList.add(Fragment.instantiate(this,Fragment3.class.getName())); 



     fList.add(MyAccountFragment.newInstance(this,"My Account")); 
     fList.add(ReportFragment.newInstance(this,"Reports")); 
     fList.add(SettingsListFragment.newInstance(this,"Settings")); 

     return fList; 
    } 

調用適配器::

actionbartabmenuAdapter = new ActionBarTabMenuAdapter(getSupportFragmentManager(), fragments,this); 
awesomePager.setAdapter(actionbartabmenuAdapter); 

適配器::

private class ActionBarTabMenuAdapter extends FragmentPagerAdapter { 
     Activity context; 
     Context ctx; 
     private List<Fragment> fragments; 

     public ActionBarTabMenuAdapter(FragmentManager fm, List<Fragment> fragments,Context ctx,) 
     { 
      super(fm); 
      this.context=(Activity) ctx; 

      this.fragments = fragments; 
     } 

     @Override 
     public int getCount() 
     { 
      return fragments.size(); 
     } 
     @Override 
     public Fragment getItem(int position) { 

      System.out.println("position of fragment--"+position); 
      return this.fragments.get(position); 
     } 
    } 

onTabSelected /重選方法::

@Override 
    public void onTabReselected(Tab tabposition, FragmentTransaction fragmentposition) { 
     System.out.println("Tab Reselected method"); 

    } 

    @Override 
    public void onTabSelected(Tab tabposition, FragmentTransaction fragmentposition) { 

     awesomePager.setCurrentItem(tabposition.getPosition()); 
    } 

    @Override 
    public void onTabUnselected(Tab tabposition, FragmentTransaction fragmentposition) { 
     System.out.println("Tab unselected method"); 

    } 

MyAccountFragment ::

public class MyAccountFragment extends SherlockFragment{ 

    static MyAccountFragment f ; 
    ListView list_subscriberInfo; 
    ProgressDialog pd = null; 
    MyAccountInfo myAccountInfo = new MyAccountInfo(); 
    private MyApplication appContext; 
    static Context context; 

    public static MyAccountFragment newInstance(Activity ctx,String string) 
    { 
     f = new MyAccountFragment(); 
     context=ctx; 
     return f; 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     getSherlockActivity().supportInvalidateOptionsMenu(); // now onCreateOptionsMenu(...) is called again 
     this.setHasOptionsMenu(true); 
    } 

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

     View v = inflater.inflate(R.layout.my_account, container, false); 
     list_subscriberInfo = (ListView)v.findViewById(R.id.list_subscriberInfo); 

     return v; 
    } 

    @Override 
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) 
    { 
     super.onCreateOptionsMenu(menu, inflater); 
     inflater.inflate(R.menu.menu_new, menu); 
    } 

    public void onPrepareOptionsMenu(Menu menu) 
    { 
     super.onPrepareOptionsMenu(menu); 
    } 
    public void setUserVisibleHint(boolean isVisibleToUser) 
    { 
     super.setUserVisibleHint(isVisibleToUser); 
     pd=new ProgressDialog(context); 
     if (isVisibleToUser) 
     { 
      pd =ProgressDialog.show(context,null, "Please Wait..", true); 
      pd.setContentView(R.layout.progress); 
      Thread thread = new Thread(getPersonalInfo); 
      thread.start(); 
     } 
     else 
     { 
      if(pd.isShowing()) 
      { 
       pd.dismiss(); 
      } 
     } 
    } 
} 

請注意myAccountFragment我已經設置setUserVisibleHint()僅當dislpay帳戶信息這個片段的可見性是真的。

我知道我的問題的解決方案是setOffScreenLimit(),但我不知道在哪裏/如何設置它的實現。

但是,如何使用這兩種方式只有當我的帳戶可見時,片段纔可見,也不會每次加載片段。僅在刷新按鈕在操作欄(第二次)中單擊時才加載。

希望我清楚。

在此先感謝...

編輯::

應用LuksProg的邏輯......

MyContainerActivity ::

MyAccountFragment mSavedAccount; 

public void cacheAccount(MyAccountFragment account) { 
     mSavedAccount = account; 
    } 

    public Object getCachedAccount() { 
     return mSavedAccount; 
    } 

MyAccountFragment ::

@Override 
    public void onActivityCreated(Bundle savedInstanceState) 
    { 
     super.onActivityCreated(savedInstanceState); 
     containerActivity = (ButtonPayActivity) getActivity(); 
     pd=new ProgressDialog(context); 

     if (containerActivity.getCachedAccount() != null) 
     { 
      //Do nothing 
      if(pd.isShowing()) 
      { 
       pd.dismiss(); 
      } 
     } 
     else 
     { 
      // the data isn't available so this must be a fresh start 
      // start the thread, remember to use act.cacheAccount() when the thread finishes 
      pd =ProgressDialog.show(context,null, "Please Wait..", true); 
      pd.setContentView(R.layout.progress); 
      Thread thread = new Thread(getPersonalInfo); 
      thread.start(); 
     } 
    } 

編輯2 ::

應用邏輯進度對話框後,我面臨着以下問題。

我所做的是展示和取消的進度對話框但之後,我搬到我的應用程序得到墜毀我的賬戶的第二天標籤...

awesomePager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { 

      @Override 
      public void onPageSelected(int position) 
      { 
       //supportInvalidateOptionsMenu(); 
       actionBar.setSelectedNavigationItem(position); 
       if (position == 4) 
       { 
         MyAccountFragment df = (MyAccountFragment) actionbartabmenuAdapter.getItem(position); 
        if (df.getThread() != null && df.getThread().isAlive()) 
        { 
         df.showDialog(); 
        } 
        else 
        { 
         df.cancelDialog(); 
        } 
       } 
      } 

      @Override 
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 
       super.onPageScrolled(position, positionOffset, positionOffsetPixels); 
      } 

      @Override 
      public void onPageScrollStateChanged(int state) { 
       super.onPageScrollStateChanged(state); 
      } 
     }); 

myAccountFragment ::

@Override 
    public void onActivityCreated(Bundle savedInstanceState) 
    { 
     super.onActivityCreated(savedInstanceState); 
     containerActivity = (ButtonPayActivity) getActivity(); 
     pd=new ProgressDialog(context); 

     if (containerActivity.getCachedAccount() != null) 
     { 

      if(pd.isShowing()) 
      { 
       pd.dismiss(); 
      } 
     } 
     else 
     { 

      pd =ProgressDialog.show(context,null, "Please Wait..", true); 
      pd.setContentView(R.layout.progress); 
      thread = new Thread(getPersonalInfo); 
      thread.start(); 
     } 
    } 

    public void showDialog() 
    { 
     if (pd != null) 
     { 
      pd.show(); // the dialog will be started from the OnPageChangeListener only 
     } 
    } 

    public void cancelDialog() 
    { 
     if (pd != null) 
     { 
      pd.dismiss(); 
     } 
    } 

    public Thread getThread() 
    { 
     return thread; 
    } 

的logcat ::

12-24 20:31:20.076: E/AndroidRuntime(15596): FATAL EXCEPTION: main 
12-24 20:31:20.076: E/AndroidRuntime(15596): java.lang.ClassCastException: com.example.app.home.ReportFragment 
12-24 20:31:20.076: E/AndroidRuntime(15596): at com.example.app.ContainerActivity$1.onPageSelected(ContainerActivity.java:151) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:438) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:405) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:386) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at com.example.app.ContainerActivity.onTabSelected(ContainerActivity) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at com.actionbarsherlock.internal.app.ActionBarImpl.selectTab(ActionBarImpl.java:531) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at com.actionbarsherlock.internal.app.ActionBarImpl$TabImpl.select(ActionBarImpl.java:912) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at com.actionbarsherlock.internal.widget.ScrollingTabContainerView$TabClickListener.onClick(ScrollingTabContainerView.java:504) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at android.view.View.performClick(View.java:2485) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at android.view.View$PerformClick.run(View.java:9080) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at android.os.Handler.handleCallback(Handler.java:587) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at android.os.Handler.dispatchMessage(Handler.java:92) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at android.os.Looper.loop(Looper.java:130) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at android.app.ActivityThread.main(ActivityThread.java:3683) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at java.lang.reflect.Method.invokeNative(Native Method) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at java.lang.reflect.Method.invoke(Method.java:507) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 
12-24 20:31:20.076: E/AndroidRuntime(15596): at dalvik.system.NativeStart.main(Native Method) 

仍然存在的問題,只是爲了好奇,我在我的代碼中應用了以下事情,但沒有成功。 現在我得到的進度對話框之前myAccount片段得到可見性,所以我申請onActivityCreated()setUserVisibleHint()並保持其餘的東西,因爲它。

但後來也是我的應用進行了崩潰,我得到了以下日誌..

的logcat ::

12-24 20:22:26.125: E/AndroidRuntime(14861): FATAL EXCEPTION: main 
12-24 20:22:26.125: E/AndroidRuntime(14861): java.lang.NullPointerException 
12-24 20:22:26.125: E/AndroidRuntime(14861): at com.example.app.home.MyAccountFragment.setUserVisibleHint(MyAccountFragment.java:183) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at android.support.v4.app.FragmentPagerAdapter.instantiateItem(FragmentPagerAdapter.java:102) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:649) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at android.support.v4.view.ViewPager.populate(ViewPager.java:783) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:433) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:405) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:386) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at com.example.app.ContainerActivity.onTabSelected(ContainerActivity.java:385) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at com.actionbarsherlock.internal.app.ActionBarImpl.selectTab(ActionBarImpl.java:531) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at com.actionbarsherlock.internal.app.ActionBarImpl$TabImpl.select(ActionBarImpl.java:912) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at com.actionbarsherlock.internal.widget.ScrollingTabContainerView$TabClickListener.onClick(ScrollingTabContainerView.java:504) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at android.view.View.performClick(View.java:2485) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at android.view.View$PerformClick.run(View.java:9080) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at android.os.Handler.handleCallback(Handler.java:587) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at android.os.Handler.dispatchMessage(Handler.java:92) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at android.os.Looper.loop(Looper.java:130) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at android.app.ActivityThread.main(ActivityThread.java:3683) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at java.lang.reflect.Method.invokeNative(Native Method) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at java.lang.reflect.Method.invoke(Method.java:507) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 
12-24 20:22:26.125: E/AndroidRuntime(14861): at dalvik.system.NativeStart.main(Native Method) 
+0

是你的應用程序包含ABS +選項卡+ multifragments?對? – Sharmilee

+0

@Sharmilee是的,你是絕對正確的...... – AndroidLearner

回答

2

我想要加載的我的帳戶詳細資料只有一次(第一次)片段 被加載,而不是每次(現在正在發生)。

如果您只想加載一次數據,那麼一旦您第一次檢索到數據,您就需要將其緩存在活動/碎片級別。所以,你將需要實現你的Activity兩種方法包含片段來設置和獲取數據:

public void cacheAccount(Object account) { 
    mSavedAccount = account; 
} 

public Object getCachedAccount() { 
    return mSavedAccount; 
} 

然後在MyAccountFragment片段將實現以下邏輯:

  • 使用一個的生命週期方法把代碼檢索數據(所以,不要使用setUserVisibleHint()),如onActivityCreated()
  • 那裏,您將需要使用上述方法來首先看看數據是否已經不可用(如果該片段之前被加載並且dat一個被保存)。如果數據可用,則直接使用它並且不要啓動檢索步驟,否則啓動線程
  • 如果線程已啓動,當它完成時,您需要設置數據並將其保存到活動中,以便它將可在MyAccountFragment片段的未來用途

模擬實現:

// in the onActivityCreated() method: 
// cast the activity 
YourActivity act = (YourActivity) getActivity(); 
// check if the data isn't by any chance already available 
if (act.getCachedAccount() != null) { 
    // the data is already available so use it 
} else { 
    // the data isn't available so this must be a fresh start 
    // start the thread, remember to use act.cacheAccount() when the thread finishes 
} 

另外,如果你想保存整個配置更改的數據,你可能想使用一個片段與上面的方法它被設置爲保留配置(爲其調用setRetainInstance(true))。

而且,我想設置在操作欄中一個刷新按鈕,這樣對刷新按鈕/圖片的點擊 帳戶詳細信息將負載和 顯示。

這應該不是問題,因爲只要您在檢索線程完成時記得調用activity.cacheAccount(),以便將來可以使用這些數據。

我知道我的問題的解決方案是setOffScreenLimit(),但我不知道在哪裏/如何將它設置爲我的實現。

setOffScreenLimit()將增加適配器在內存中保留的片段數量。取決於你的碎片有多重,它可能會工作,但一般來說,你應該避免使用更大的值(在你的情況下,你基本上將記憶所有ViewPager的碎片)。

請注意,您的當前實施ViewPager的適配器(將預構建片段列表傳遞給它)將在某些情況下失敗,因爲您構建的片段列表不會保存片段ViewPager實際使用。

編輯 實現:

private SparseArray<Fragment> getFragments() { 
    // I used a SparseArray but a list will also do 
    SparseArray<Fragment> fList = new SparseArray<Fragment>(); 
    fList.put(Fragment.instantiate(this,Fragment1.class.getName())); 
    fList.put(Fragment.instantiate(this,Fragment2.class.getName())); 
    fList.put(Fragment.instantiate(this,Fragment3.class.getName())); 
    fList.put(MyAccountFragment.newInstance(this,"My Account")); 
    fList.put(ReportFragment.newInstance(this,"Reports")); 
    fList.put(SettingsListFragment.newInstance(this,"Settings")); 
    return fList; 
} 

// the adapter 
private class ActionBarTabMenuAdapter extends FragmentPagerAdapter { 
     Activity context; 
     Context ctx; 
     private SparseArray<Fragment> fragments; 

     public ActionBarTabMenuAdapter(FragmentManager fm, SparseArray<Fragment> fragments,Context ctx) { 
      super(fm); 
      this.context=(Activity) ctx; 
      this.fragments = fragments; 
     } 

     @Override 
     public int getCount() { 
      return fragments.size(); 
     } 

     @Override 
     public Fragment getItem(int position) { 
      System.out.println("position of fragment--"+position); 
      return this.fragments.get(position); 
     } 

     @Override 
    public void destroyItem(ViewGroup container, int position, Object object) { 
     fragments.put(position, null); 
     super.destroyItem(container, position, object); 
    } 

     @Override 
    public Object instantiateItem(ViewGroup container, int position) { 
     Fragment f = (Fragment) super.instantiateItem(container, position); 
     fragments.put(position, f); 
     return f; 
    } 
    } 

第二個編輯: 要顯示對話框,只有當你在MyAccountFragment片段:

mViewPager.setOnPageChangeListener(new OnPageChangeListener() { 

@Override 
public void onPageSelected(int position) { 
    if (position == 3) { 
       MyAccountFragment df = (MyAccountFragment) adapter.getItem(position); 
      if (df.getThread() != null && df.getThread().isAlive()) { 
       df.showDialog(); 
      } else { 
       df.cancelDialog(); 
      } 
     } 
    } 

// rest of the methods 
} 

而這些方法在MyAccountFragment實施:

public void showDialog() { 
     if (pd != null) { 
      pd.show(); // the dialog will be started from the OnPageChangeListener only 
     } 
    } 

    public void cancelDialog() { 
     if (pd != null) { 
      pd.dismiss(); // remeber to call this when the thread finishes 
     } 
    } 

    public Thread getThread() { 
     return mThread; // this will be the reference to the started thread 
    } 
+0

正如你所說,我目前的viewpager實現可能會在某些情況下失敗。所以你可以請在那部分糾正我? – AndroidLearner

+0

@AndroidLearner我用一個例子編輯了我的答案。您需要保持引用同步。 – Luksprog

+0

'fragments.delete(position);'''和fragments.put(position,f);'顯示我一個錯誤'方法put(int,Fragment)未定義類型List ' – AndroidLearner