android getChildAt(index)返回null問題解決方法


  getChildAt(index)方法ViewGroup類的方法,許多需要adapter的類(List,GridView)都可以使用這個方法。今天就用到了getChildAt(index)方法,我用的是GridView,需要在數據庫中讀出GridView中的某些項目,給這些子項替換背景(就是打個勾標記的背景),但是,卻發現getChildAt(index)方法返回值一直為null,很是不理解。

  下面做個demo重現該問題:

  java代碼:

 1 import java.util.ArrayList;
 2 import java.util.HashMap;
 3 import java.util.Map;
 4 
 5 import android.os.Bundle;
 6 import android.app.Activity;
 7 import android.graphics.Color;
 8 import android.util.Log;
 9 import android.widget.GridView;
10 import android.widget.SimpleAdapter;
11 
12 public class MainActivity extends Activity {
13 
14     ArrayList<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
15     SimpleAdapter adapter;
16     GridView gv;
17     
18     @Override
19     public void onCreate(Bundle savedInstanceState) {
20         super.onCreate(savedInstanceState);
21         setContentView(R.layout.activity_main); 
22         gv = (GridView)findViewById(R.id.gv);       
23         gv.setNumColumns(7);
24         gv.setVerticalSpacing(50);
25                 
26         final String [] number = new String[]
27                 {
28                 "1","2","3","4","5","6","7","8","9","10",
29                 "11","12","13","14","15","16","17","18","19","20"
30                 };
31         final ArrayList<Map<String,Object>> list = new ArrayList<Map<String,Object>>();
32        
33         for(int i=0;i<number.length;i++)
34         {
35             Map<String,Object> listitem = new HashMap<String,Object>();            
36             listitem.put("id", number[i]);
37             list.add(listitem);
38         }
39         
40 
41         adapter = new SimpleAdapter(this
42                 ,list
43                 ,R.layout.list
44                 ,new String[]{"id"}
45                 ,new int[]{R.id.tv});
46         gv.setAdapter(adapter);
47 //        Log.v("gv.getChildAt(5)", ""+gv.getChildAt(5));                         (1)
48 //        gv.getChildAt(5).findViewById(R.id.tv).setBackgroundColor(Color.BLUE);   (2)
49     }
50 }

  xml布局文件:

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="match_parent"
 3     android:layout_height="match_parent" >
 4 
 5     <GridView 
 6         android:id="@+id/gv"
 7         android:layout_width="fill_parent"
 8         android:layout_height="wrap_content"
 9         />
10 
11 </RelativeLayout>

  list.xml

<RelativeLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textColor="#000000"
        />
 
</RelativeLayout>

 

  以上程序將正常運行:

  然后將上面注釋的兩行代碼去掉,程序出錯:

  正如上面所說是空指針錯誤,看代碼(1)那行的輸出:

  百思不得其解之后,請來UI組的師傅給找原因,他用了Handler類實現了:(把上面java代碼中注釋掉的兩行代碼,換成以下代碼)

1 Handler handler = new Handler();        
2         handler.postDelayed(new Runnable() {            
3             public void run() {
4                 // TODO Auto-generated method stub
5                 gv.getChildAt(5).findViewById(R.id.tv).setBackgroundColor(Color.BLUE);
6             }
7         }, 500);

  運行結果:

   師傅說是因為setadapter()方法不是立即就執行好的,而是要用到計算機時間片輪轉的規則,所以稍微延遲執行后面的getChildAt(index)方法,就不會返回null了。但是,做產品的時候,這種延遲的方法也不是合適的方法,萬一用戶后台執行了大量程序,CPU工作的效率很低,幾個時間片都沒有完成setadapter()方法,這就成為了bug,如果把延遲時間拉長,又會影響用戶體驗。

  所以,一般情況下,要改變GridView的某一項的狀態(改變背景等),而這種改變並不是隨事件觸發(click事件,select事件等),而是一開始就有(如從數據庫中讀取),那么應該自定義adapter,重寫它的getView()方法,以便直接在setadapter()時就完成要做的事,不用在代碼中手動更改。如果需要動態改變,onItemXXXListener方法中可以實現。

  由於這次的困擾,也發現自己對適配器的工作原理還是十分的不熟悉,實現重寫adapter的getView()方法,也是參考了別人已經做好的東西,所以實現重寫adapter的getView()方法這里就不說了,網上有很多,等自己掌握了之后,再補上吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM