使用AsyncHttpClient碰到的問題及解決方法

以前作一個項目,項目裏面的佈局是這樣的:一個ViewpagerViewpager裏面有三個Fragment,在第二個Fragment裏面有一個ListView,使用了BaseAdapter來顯示item。當時由於圖方便,把獲取數據源mData的方法直接寫在了adapter的構造方法裏面,數據源經過syncHttpClient向後臺請求參數獲取。api

 

大概的代碼以下:app

1 private LayoutInflater mInflater;less

 2 private static List<Map<String, Object>> mData = new ArrayList<Map<String, Object>>();異步

 3 private RequestQueue queue;async

 4 private ImageLoader imageLoader;ide

 5 private Context context;佈局

 6 private UserInfoEntity userInfoEntity;性能

 7this

 8 public LessonEndingAdapter(Context context) {url

 9        this.context = context;

10        mInflater = LayoutInflater.from(context);

11        AuthCheck ac = new AuthCheck();

12        this.userInfoEntity = ac.getUserInfo(context);

13        queue = Volley.newRequestQueue(context);

14        imageLoader = new ImageLoader(queue, new BitmapCache());

15        init();

16 }

17 private void init() {

18        mData.clear();

19        String url = Codes.URL_ROOT + "/lesson/studied.api?" + "userid="+ context.getSharedPreferences(Codes.USERINFO, 0).getInt(Codes.USERID, 0) + "&token="+ context.getSharedPreferences(Codes.USERINFO, 0).getString(Codes.TOKEN, "");

20        SyncHttpClient client = new SyncHttpClient();

21        client.get(url, new JsonHttpResponseHandler() {

22            @Override

23            public void onSuccess(int statusCode, Header[]     headers,JSONObject response) {

24        super.onSuccess(statusCode, headers, response);

25        if (statusCode == 200) {   

26              processJsonData(response);

27        }

28    }

29   });

30 }

 

這裏就不詳細的講SyncHttpClient的用法了,只說說我在使用過程當中碰到的一些問題和解決辦法。

 

      當時我在init()中用的是AsyncHttpClient(代碼裏面是SyncHttpCilent),沒在乎AsyncHttpClientSyncHttpClient的區別,隨意挑了前者,結果問題就出現了:

 

第一次init沒有問題,可是當init操做執行幾回後,頁面變成了空白一片,listView中的item都消失了。

 

      我在adapterinit(),getView(),getCount()中都寫了Log,發現init()方法中的mData成功獲取了數據,可是getCount方法中顯示item數目爲0,而getView中的log更是直接就沒打印出來。通常來講,在一個類中,代碼的執行順序確定是:變量聲明->構造方法->其餘方法,因此init()應該是在getCountgetView以前執行的。如今數據獲取到了,可是卻沒有在佈局中顯示出來,慣性思惟下,我以爲應該是adapter出現了問題。

 

      我先從adapternotifyDataSetChanged()方法入手,一步步點進去,最後進入notifyChanged()方法,代碼以下:

1 public void notifyChanged(){

2    synchronized(mObservers){

3      //since onChanged() is implemented by the app,it could do anything,including

4      //removing itself from{@link mObservers}-and that could cause problem if

5      //an iterator is used om the ArrayList{link mObservers}.

6      //to avoid such problems,just march thru the list in the reverse order.

7      for(int i = mObservers.size() - 1;!>=0;i--){

8        mObservers.get(i).onChanged();

9      }  

10   }

11 }

 

從字面上看,就是一個循環,對每個item進行判斷是否改變,若改變的話對佈局進行修改。但如今的問題是getCount0,也就是說並未進行這個循環,經過Log打印的順序,我對getViewLog沒打出來的問題有了大體的猜測:

 

      adapter中方法執行的順序爲:構造方法->getCount->getView,其餘方法在adapter中並非必不可少的,暫且不論。當listView綁定了一個adapter時,程序會執行構造方法,而後執行getCount()getCount()會重複執行幾遍,當getCount方法不爲0時,執行getView方法。若getCount()一直爲0,那麼就不執行getView(),佈局天然而然就不會顯示出來。

 

      如今的問題就是,數據取到了(mData有數據),可是getCount爲何一直爲0呢?我想來想去也只有從第三方類庫SyncHttpClient入手了。在網上查了一下SyncHttpClientAsyncHttpClient的特性,發現字面意思已經表達的很清楚了:sync->同步,async->異步……也就是說,當用AsyncHttpClient時,程序會自動新開一個線程,數據獲取在一個線程,而adapter中的getCount又在另外一個線程,二者的進度是沒法把握的。結果很明顯了,雖然是init()方法先執行,可是因爲AsyncHttpCilent新開了一個線程,致使在請求參數的過程當中,getCount()也已經開始執行,AsyncHttpClient是一個較爲耗時的操做,因此每次getCount都先於client.get執行完畢,這就解釋了爲何getCount一直爲0mData又不爲空了!

 

      既然發現了問題那就很好解決了,最簡單的方法就是把AsyncHttpClient改爲SyncHttpClient。可是這樣作性能不好,這就失去了異步操做存在的意義了。個人方法是在AsynHttpClient方法的末尾,即數據取完以後,加一個adapter.notifyDataSetChanged(),這時程序會自動再次執行getCount,很顯然此次的getCount就不爲0了,緊接着就執行getView顯示佈局,ok,問題解決。固然,開發完APP也是須要進行全方位的檢測:www.ineice.com

相關文章
相關標籤/搜索