天天看點

【ItemizedOverlay的ArrayIndexOutOfBoundsException/NullPointerException異常解決辦法】

    bill在前文說道Android Google Map API中有很多小陷阱,本文将介紹bill在開發過程中遇到的其中一個并給出解決方案。

    通過前面的介紹,我們知道可以通過繼承Android Google Map API中的ItemizedOverlay來自定義我們需要的疊加層。既然是自定義疊加層,就應該為它編寫“添加”、“删除”以及“清空”等常用功能,于是我們前面編寫的HelloItemizedOverlay可以改寫為下面的樣子<b></b>

import android.content.Context; 

import android.graphics.Canvas; 

import android.graphics.drawable.Drawable; 

import com.google.android.maps.ItemizedOverlay; 

import com.google.android.maps.MapView; 

import com.google.android.maps.OverlayItem; 

@SuppressWarnings("rawtypes") 

public class HelloItemizedOverlay extends ItemizedOverlay { 

    private ArrayList&lt;OverlayItem&gt; mOverlayItems = new ArrayList&lt;OverlayItem&gt;(); 

    private Context mContext = null; 

    public HelloItemizedOverlay(Drawable defaultMarker) { 

        super(boundCenterBottom(defaultMarker)); 

    } 

    public HelloItemizedOverlay(Drawable defaultMarker, Context context) { 

        mContext = context; 

    @Override 

    protected OverlayItem createItem(int i) { 

        OverlayItem item = null; 

        try { 

            item = mOverlayItems.get(i); 

        } catch (ArrayIndexOutOfBoundsException e) { 

            e.printStackTrace(); 

        } catch (IndexOutOfBoundsException e) { 

        } catch (Exception e) { 

        } 

        return item; 

    public int size() { 

        return mOverlayItems.size(); 

    protected boolean onTap(int index) { 

      return true; 

    /** 

     * add new overlay item into overlay items array 

     *  

     * @param overlay 

     */ 

    public void addOverlay(OverlayItem overlay) { 

            mOverlayItems.add(overlay); 

            populate(); 

     * remove overlay item 

    public void remove(OverlayItem overlayItem) { 

            mOverlayItems.remove(overlayItem); 

     * clear overlay 

    public void clear() { 

            mOverlayItems.clear(); 

     非常簡單的邏輯,看似毫無破綻,于是bill就興高采烈地用這個“陷阱工具”進行程式的開發了,開始還好,我隻是示意性地往疊加層中添加1~2個圖示,程式安然無恙地運作着。也怪自己大意,沒有一點對它進行測試的意識,就這樣帶着陷阱一直開發,直到我有必要向疊加層添加更多的圖示并根據程式邏輯進行删除時,才發現程式總是莫名其妙地崩潰,要麼得到ArrayOutOfBoundsException,要麼得到NullPointerException,于是bill開始各種try...catch...可惜手頭并無Google源碼,異常捕獲工作也隻是徒勞無功。

    根據google自己的doc說明,每次對Overlay List中的資料進行更新後,需要調用populate()方法,以便将更新同步到UI,然而,事實遠非如此,ItemizedOverlay這個類自己還記錄了最後一個具有焦點的OverlayItem的下标,并且還使用這個下标維持諸如lastFocusedIndex等内部資料,而當我們更新(增、删)Overlay清單時,ItemizedOverlay并不保證lastFocuedIndex的正确性,是以當ItemizedOverlay内部再次使用已經不正确的lastFocusedIndex時,一切就可想而知了。

    解決辦法就是在我們每次更新之後,主動地設定lastFocusedIndex的值為-1,表示從來沒有哪一個item在最近獲得過焦點,這将使得其内部調用nextFocus(boolean forwords)時傳回清單中的第一個item或者null,如此便能直接消除該異常或産生我們可以在自己代碼中捕獲并進行相關處理的異常。

    其次,當我們不向Overlay清單中添加任何項就直接顯示時,還會得到NullPointerException,異常源于google的一個bug,當時被标注為未修複,解決辦法是在構造函數的末尾調用populate()方法。

    根據上述說明,代碼修改如下: 

        //fix the NullPointerException bug 

        populate(); 

            //主動設定lastFocusedIndex = -1 

            setLastFocusedIndex(-1); 

     * clear overlays 

    至此,bill已将自己在Android Google Map API的ItemizedOverlay中遇到的陷阱及其解決方法介紹完畢,現在便可以安全地使用HelloItemizedOverlay類進行接下來的開發了。

     本文轉自Bill_Hoo 51CTO部落格,原文連結:http://blog.51cto.com/billhoo/977474,如需轉載請自行聯系原作者

繼續閱讀