2011-10-12 69 views
16

我試圖使用FragmentActivityViewPager來顯示動態列表Fragments。有很多關於如何做靜態版本的例子。我的問題是我顯示的列表需要動態加載,也可以根據用戶輸入(添加/刪除)進行更改。我正嘗試使用自定義的android.support.v4.content.Loader加載可用於構建我的列表的數據集。Android - 使用FragmentActivity + Loader更新FragmentStatePagerAdapter的問題

一切順利在我的設置很好,直到我去點時,我想更新適配器,併發出此時該代碼被執行(從FragmentStatePagerAdapterFragmentStatePagerAdapter#notifyDataSetChanged()呼叫

public void finishUpdate(View container) 
{ 
    if(mCurTransaction != null) 
    { 
     mCurTransaction.commit(); // BANG!!! The exception is thrown 
     mCurTransaction = null; 
     mFragmentManager.executePendingTransactions(); 
    } 
} 

提交失敗與交易此消息:

java.lang.IllegalStateException: Can not perform this action inside of onLoadFinished

因爲內FragmentManagerImpl執行該代碼:

private void checkStateLoss() { 
    if (mStateSaved) { 
     throw new IllegalStateException(
       "Can not perform this action after onSaveInstanceState"); 
    } 
    if (mNoTransactionsBecause != null) { 
     throw new IllegalStateException(
       "Can not perform this action inside of " + mNoTransactionsBecause); 
    } 
} 

事實證明,mNoTransactionsBecause值不爲空,它是在LoaderManagerImpl.LoaderInfo設定時,返回的結果回onLoadFinished

我一直在尋找各種變量試圖以某種方式改變tramsaction.commit()transaction.commitAllowingStateLoss()但一切相關交易似乎是私人的,或者至少是包裹保護的。

如果我可以做我需要做的事情(以及如何做),有人可以給我一個總體想法嗎?

只是要注意的是我的代碼工作正常,如果不是使用裝載機我的AsyncTask

+0

你已經能夠找出正確的方法用裝載機做到這一點?我面臨同樣的問題。我可以使用'transaction.commitAllowingStateLoss()'來實現它的功能,但是知道Google希望我們做什麼仍然很好......似乎應該有一種在加載數據後執行片段事務的方法使用加載程序... – ashughes

+0

我通常放棄了這一點,並使用ModernTaskLoader以限制彙集 – Bostone

+0

什麼是ModernTaskLoader?在任何地方都找不到任何信息... – ashughes

回答

35

我有一個非常類似的問題,並通過在碎片上使用處理程序來解決它。

我想表現的onLoadFinished(),類似於以下

public class MyFragment extends Fragment 
    implements LoaderManager.LoaderCallbacks<T> { 

    public void onLoadFinished(Loader<T> loader, T data) { 
     showDialog(); 
    } 

    public void showDialog() { 
     MyAlertDialogFragment fragment = new MyAlertDialogFragment(); 
     fragment.show(getActivity().getSupportFragmentManager(), "dialog"); 

    } 
} 

一個警告對話框但是,這給了一個錯誤

不能的onLoadFinished

內執行此操作解決方案是在該片段中添加處理程序,以便顯示對話框

private Handler handler = new Handler() { 
    @Override 
    public void handleMessage(Message msg) { 
     if(msg.what == MSG_SHOW_DIALOG) { 
      showDialog(); 
     } 
    } 
}; 

然後修改onLoadFinished(...)將消息發送到處理程序,而不是

public void onLoadFinished(Loader<T> loader, T data) { 
     handler.sendEmptyMessage(MSG_SHOW_DIALOG); 
    } 
+11

或者您可以將處理程序發佈到runnable。 'Handler h = new Handler(Looper.getMainLooper());h.post(new Runnable(){....});'等 –

+1

@ Chris.Jenkins Ian的實現更高效,因爲它只需要一個對象分配。 :) –

+0

@AlexLockwood除非在高性能場景中一次創建1000個對象,否則不是真正的問題。 –

0

運行負荷OPS您可以複製FragmentStatePagerAdapter和你喜歡的更改,或從頭開始創建自己的PagerAdapter。或者乾脆不要使用Loader。

+0

這不是適配器的問題,它只是在進行交易。但有人花費了相當大的力氣來阻止onLoadFinished中的交易提交。我想知道爲什麼?我也不喜歡爲了一行而重寫類而且我喜歡Loader概念並想使用它。正如我所說 - 我確實有工作實施直接使用AsyncTask – Bostone

+4

顯然是因爲調用'onLoadFinished()'時有可能失去狀態。從JavaDoc:'請注意,通常應用程序不允許在此調用中提交片段事務,因爲它可能在保存活動狀態後發生。有關這方面的進一步討論,請參閱FragmentManager.openTransaction()。 '你必須改變適配器才能使用'commitAllowingStateLoss()'或者取消加載器。我遇到了同樣的問題,下面是我得到的答案:https://groups.google.com/forum/#!topic/android-developers/dXZZjhRjkMk/discussion –

0

它的工作原理使用rootView.post()。只需在類作用域中定義rootView變量,然後將其充注到onCreateView()。 最後onLoadFinished()簡單地使用這樣的:

  rootView.post(new Runnable() { 
       public void run() { 
        General.showFragment(); 
       } 

      });