Custom ArrayAdapter: why do I get a NullPointerExc

2019-05-29 00:43发布

问题:

Sorry for bothering people so proficient, but I am new to Android and I am trying to learn...

Anyway, I am trying to build a Gallery with a custom adapter.

But I get NullPointerException as soon as the program tries to invoke the adapter.

Any help very much appreciated!!!!

public class MainActivity extends Activity {
    private Gallery gal;
    private List<Elementi> el;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        List<Elementi> el = new ArrayList<Elementi>();
        int[] tabDrawables = new int[] {
                     R.drawable.img1,R.drawable.img2,R.drawable.img3,R.drawable.img1,R.drawable.img4,R.drawable.    img5,R.drawable.img6,R.drawable.img7,R.drawable.img8,R.drawable.img9,R.drawable.img10};

        String[] descrizione =    {"cani","boffo","gigo","belo","fyyfy","bogin","boginetti","zippe","ninne","cestino","cagnin    o","cucciolo",};

        for (int numero =1; numero <= 10;numero++) {

            ImageView imgm = new ImageView(this);
            imgm.setImageResource(tabDrawables[numero]);
            el.add(new Elementi(imgm,descrizione[numero]));

        };


        super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
        Gallery gal=(Gallery)findViewById(R.id.galleria);
        gal.setAdapter(new MyAdapter());


    }
public class MyAdapter extends ArrayAdapter<Elementi> {
    public MyAdapter() {
        super(MainActivity.this, R.layout.row, el);
    }   
    public View getView(int position, View convertView,ViewGroup parent) {
                View row= convertView;  
                TextView txt =(TextView)row.findViewById(R.id.testorow);
                txt.setText(el.get(position).tx) ;
                ImageView ima =(ImageView)row.findViewById(R.id.immagine);
                ima.setImageResource(R.drawable.img1);
                Toast.makeText(getApplicationContext(), Inte    ger.toString(position), Toast.LENGTH_LONG).show();      
                return row;};

}    


public class Elementi { 
public ImageView im;
public String tx; 
public Elementi(ImageView img,String txt){
        ImageView im =img;
        String tx = txt;        

    }

}

}

My LogCat:

11-29 20:26:28.327: E/AndroidRuntime(786): FATAL EXCEPTION: main
11-29 20:26:28.327: E/AndroidRuntime(786): java.lang.RuntimeException: Unable to start     activity ComponentInfo{com.example.gallery/com.example.gallery.MainActivity}:    java.lang.NullPointerException
11-29 20:26:28.327: E/AndroidRuntime(786):  at      android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
11-29 20:26:28.327: E/AndroidRuntime(786):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
11-29 20:26:28.327: E/AndroidRuntime(786):  at android.app.ActivityThread.access$600(ActivityThread.java:141) 
11-29 20:26:28.327: E/AndroidRuntime(786):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
11-29 20:26:28.327: E/AndroidRuntime(786):  at android.os.Handler.dispatchMessage(Handler.java:99)
11-29 20:26:28.327: E/AndroidRuntime(786):  at android.os.Looper.loop(Looper.java:137)
11-29 20:26:28.327: E/AndroidRuntime(786):  at android.app.ActivityThread.main(ActivityThread.java:5039) 
11-29 20:26:28.327: E/AndroidRuntime(786):  at java.lang.reflect.Method.invokeNative(Native Method)
11-29 20:26:28.327: E/AndroidRuntime(786):  at java.lang.reflect.Method.invoke(Method.java:511)
11-29 20:26:28.327: E/AndroidRuntime(786):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
11-29 20:26:28.327: E/AndroidRuntime(786):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
11-29 20:26:28.327: E/AndroidRuntime(786):  at dalvik.system.NativeStart.main(Native Method)
11-29 20:26:28.327: E/AndroidRuntime(786): Caused by: java.lang.NullPointerException
11-29 20:26:28.327: E/AndroidRuntime(786):  at android.widget.ArrayAdapter.getCount(ArrayAdapter.java:330)
11-29 20:26:28.327: E/AndroidRuntime(786):  at android.widget.AbsSpinner.setAdapter(AbsSpinner.java:114)
11-29 20:26:28.327: E/AndroidRuntime(786):  at com.example.gallery.MainActivity.onCreate(MainActivity.java:52)
11-29 20:26:28.327: E/AndroidRuntime(786):  at android.app.Activity.performCreate(Activity.java:5104) 
11-29 20:26:28.327: E/AndroidRuntime(786):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
11-29 20:26:28.327: E/AndroidRuntime(786):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
11-29 20:26:28.327: E/AndroidRuntime(786):  ... 11 more
11-29 20:26:28.547: D/dalvikvm(786): GC_CONCURRENT freed 387K, 17% free 2496K/3000K, paused 13ms+24ms, total 191ms

回答1:

You need to check if(convertView == null) and when it is you need to inflate a new View, or you can let the super class handle this:

public View getView(int position, View convertView,ViewGroup parent) {
    if(convertView == null)
        convertView = super.getView(position, convertView, parent);
    ...
} 

The presentations: Turbo Charge Your UI or World of ListView by lead Android programmers will help you understand how to work with getView() without slowing down your app.


Addition
From your LogCat:

Caused by: java.lang.NullPointerException
    at android.widget.ArrayAdapter.getCount(ArrayAdapter.java:330)

This means the list you passed to the ArrayAdapter is null...

This is because you have two different copies of el:

private List<Elementi> el; // This one is null and is what's passed to your adapter
@Override
protected void onCreate(Bundle savedInstanceState) {
    List<Elementi> el = new ArrayList<Elementi>(); // This one only exists in onCreate!

I don't really like how Java let's you do this without a warning... Simply change the last line to:

protected void onCreate(Bundle savedInstanceState) {
    el = new ArrayList<Elementi>();

(However you will hit another NullPointerException if you don't address getView() as stated above.)



回答2:

Without seeing the logcat, I think here's your mistake. The convertView parameter of the getView() method is null the very first time the method is called. Your job is to inflate a view when convertView == null:

public View getView(int position, View convertView,ViewGroup parent) {
   View row= convertView;  
   if(row==null){
        LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
        row = inflater.inflate(R.layout.mylayout, parent, false);    
   }

   TextView txt =(TextView)row.findViewById(R.id.testorow);
   //(...) more code
}

When getView() is called again, it uses this View as a convertView, and so convertView will probably not be null.



回答3:

I think in your Custom Adapter's getView() View row is null.

So this code line txt.setText(el.get(position).tx); gives you NullPointerException.

Actually you have to check for convertView whether it is NULL or NOT.

If convertView is NULL then you have to inflate the XML Layout again.

Something like,

View row = convertView;  
if(row == null)
{
 LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
 row = inflater.inflate(R.layout.row);    
}