2015-09-03 69 views
6

我有一個片段顯示了用MPAndroidChart創建的折線圖。加載片段大約需要200毫秒。第一次可見片段後立即執行代碼

我想通過在片段變得可見之後立即加載圖表數據數據來提高應用程序的感知性能。

因此,我需要在片段變得可見之後立即執行代碼,但僅在第一次變爲可見時執行代碼。

我不能使用onResume(),因爲它在片段可見之前被調用。

注:我不能使用異步任務,它需要在UI線程上完成。無論如何,這是沒有意義的,因爲這是一次初始化,僅需要大約200毫秒。

+0

你是說你不能把代碼放在片段的'onResume'或Activity的'onResume'上嗎? – ChrisStillwell

+0

當前代碼位於片段的onCreateView()中。無論如何,我無法使用onResume(),也無法使用onResume()和片段的onResume()。 – Mike76

+0

我不確定我在理解爲什麼你不能使用片段的'onResume'。該方法在碎片變得可見之後被調用。 – ChrisStillwell

回答

0

將它放在onViewCreated()方法中。

+2

似乎是錯誤的東西。它甚至在onResume()之前被調用。 - > ......「在onCreateView(LayoutInflater,ViewGroup,Bundle)返回後立即調用,但在任何保存的狀態恢復到視圖之前調用。 「。 – Mike76

1

在UI線程上執行任何冗長的操作都是不好的做法 - 在整個處理過程中(因爲只有一個UI線程),您將阻止整個UI。 200ms實際上很長,它是1/15秒,很容易被人眼察覺,想象你正在以5fps的幀率玩遊戲。

感知的表現就是永遠不會有UI延遲。

使用AsyncTaskAsyncTaskLoader來處理您的數據,回調將在UI線程上調用,所以不用擔心。通過將數據存儲在成員變量中,您可以控制它是否是一次性的。如果它是null - 加載,如果不是 - 立即使用。

如果你的數據是相當靜態的並且不是很大 - 在你的片段被打開之前(比如說,當Activity開始時,或者甚至當應用程序啓動時)預加載它,並且僅僅在數據正在傳遞時將數據傳遞給片段通過Bundle參數)。

+0

我無法使用AsyncTask,因爲我需要在UI線程上初始化我的圖表。 200毫秒很長,但如果沒有這張圖表,用戶將無法做任何事情。因此我只能顯示200毫秒的進度條。 – Mike76

+0

如果您花費200ms的UI線程時間,則您的進度欄將被凍結。爲什麼你需要在UI線程上處理它? –

+0

這是真的,但處理是關於更新圖表UI的。 – Mike76

6
public class MyFragment extends Fragment{ 
    Boolean _areLecturesLoaded =false; 
    @Override 
    onCreateView(){ 
    //Inflate the required views. Code gets executed once View is made but not shown 
    return v; 
} 
@Override 
    public void setUserVisibleHint(boolean isVisibleToUser) { 
     super.setUserVisibleHint(isVisibleToUser); 
     //Code executes EVERY TIME user views the fragment 

     if (isVisibleToUser && !_areLecturesLoaded) { 
      _areLecturesLoaded = true; 
      // Code executes ONLY THE FIRST TIME fragment is viewed. 
     } 
    } 
} 

isVisisbleToUser內置,當用戶查看當前片段時爲true。在用戶第一次看到該片段之前,它仍然是錯誤的。如果您希望每次用戶查看片段時都要執行一些代碼,請將該代碼放置在此區域但在if語句之外。

_areLecturesLoaded被初始化爲假,一次是第一次的片段,將其設置爲true確保如果語句不會在未來被調用,中的代碼只執行一次

的意見全部初始化窗口小部件按鈕等必須在onCreate()中完成,以確保不存在空指針和其他此類麻煩異常的可能性。

+0

謝謝我會試一試。 – Mike76

+0

讓我知道你是否面臨任何問題。否則確實接受答案。謝謝 –

+0

不幸的是,setUserVisibleHint永遠不會收到呼叫。我用android 4.4上的日誌測試了它。也許它只適用於我使用viewpager或其他東西。 – Mike76

0

它可以通過使用靜態布爾變量來實現。我使用下面的代碼僅在第一次啓動應用程序時顯示進度對話框。

public class SettingsFragment extends Fragment { 

    static boolean _areLecturesLoaded = true; 

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

     View rootView = inflater.inflate(R.layout.fragment_settings, container, false); 

     return rootView; 
    } 

    private class Getlimits extends AsyncTask<Void, Void, Void> { 
     @Override 
     protected void onPreExecute() { 
      super.onPreExecute(); 
      pd = ProgressDialog.show(getActivity(), "", "Loading...", true); 
      pd.setCancelable(false); 
     } 

     @Override 
     protected Void doInBackground(Void... arg0) { 
      //your background code 
      if(_areLecturesLoaded) { 
       try { 
        Thread.sleep(3500); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 

      return null; 
     } 
     @Override 
     protected void onPostExecute(Void result) { 
      super.onPostExecute(result); 
      // Dismiss the progress dialog 
      if (pd.isShowing()) 
       pd.dismiss(); 
      _areLecturesLoaded = false; 
     } 
    } 
}