简体   繁体   中英

String List doesn't work with Spinner ArrayAdapter

I'm building a spinner inside my activity and due to type Adapter requirements, I've to cast a List<String> to a String[] of variable length.

this is my code to retrieve objects from server (using volley ):

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.course_choice_activity);

    cChoice = (Spinner) findViewById(R.id.course_spinner);
    fChoices = new ArrayList<>();
    c = new Course();
    progressDialog = new ProgressDialog(this);
    cl = new ArrayList<>();
    sm = new SessionManager(getApplicationContext());
    rm = new RequestManager(CourseChoice.this);


    rm.getAllCourses(new VolleyCallbackOp() {
        public void onSuccess4(List<Course> cl) {
            String[] choices = new String[cl.size()];
            for (int a = 0; a < cl.size(); a++) {
                Course c = cl.get(a);
                choices[a] = c.toString();
            }
        }
    });


    ArrayAdapter<String> aa = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, choices) {
        @Override
        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            View view = super.getDropDownView(position, convertView, parent);
            TextView tv = (TextView) view;
            if (position % 2 == 1) {
                tv.setBackgroundColor(Color.parseColor("#FFC9A3FF"));
            } else {
                tv.setBackgroundColor(Color.parseColor("#FFAF89E5"));
            }
            return view;
        }
    };
    aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    //Setting the ArrayAdapter data on the Spinner
    cChoice.setAdapter(aa);
    cChoice.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
            String choice = (String) parent.getItemAtPosition(pos);
            if (choice != null) {
                Toast.makeText(getApplicationContext(), "Selected : " + choice, Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(getApplicationContext(), "An error has occurered..", Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
        }
    });

The Course toString() method return a string with its name. Inside for loop it's all right, fChoices is populated with all course names. Once outside, fChoice turn to null value and then choices too.

The adapter I've to use is the following:

ArrayAdapter<String> aa = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, choices) {...}

I tried to pass fChoices to adapter too (switching it from String to Course type but it didn't work. Anyone has an hint?

Error log:

java.lang.RuntimeException: Unable to start activity ComponentInfo{...activities.CourseChoice}: java.lang.NullPointerException
 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
 at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
 at android.app.ActivityThread.-wrap12(ActivityThread.java)
 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
 at android.os.Handler.dispatchMessage(Handler.java:102)
 at android.os.Looper.loop(Looper.java:154)
 at android.app.ActivityThread.main(ActivityThread.java:6077)
 at java.lang.reflect.Method.invoke(Native Method)
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
 Caused by: java.lang.NullPointerException
 at java.util.Objects.requireNonNull(Objects.java:203)
 at java.util.Arrays$ArrayList.<init>(Arrays.java:3826)
 at java.util.Arrays.asList(Arrays.java:3813)
 at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:139)
 at ....activities.CourseChoice$2.<init>(CourseChoice.java:99)
 at ....activities.CourseChoice.onCreate(CourseChoice.java:99)
 at android.app.Activity.performCreate(Activity.java:6662)
 at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
 at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)

Try this : define the fake course and choice data, just for testing.probably will work. the reason of your NullPointerException is that the request is executing in a different thread other than the current thread "main" .so a null value is passed to the adapter before the request is finished and your data is fetched.


Try to move adapter initialization just after the callback had finished.to make sure it's initialized in the same thread and the data is retrieved successfully.

Note : it's important to check if your data is retrieved successfully or not, that there are neither network error happened nor request timeout reached.so don't forget to check if data is not Null. you would show error message to the user.

rm.getAllCourses(new VolleyCallbackOp() {
        public void onSuccess4(List<Course> cl) {
            String[] choices = new String[cl.size()];
            for (int a = 0; a < cl.size(); a++) {
                Course c = cl.get(a);
                choices[a] = c.toString();
            }

    aa = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, choices) {
        @Override
        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            View view = super.getDropDownView(position, convertView, parent);
            TextView tv = (TextView) view;
            if (position % 2 == 1) {
                tv.setBackgroundColor(Color.parseColor("#FFC9A3FF"));
            } else {
                tv.setBackgroundColor(Color.parseColor("#FFAF89E5"));
            }
            return view;
        }
    };
    aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    //Setting the ArrayAdapter data on the Spinner
    cChoice.setAdapter(aa);
        }
    });

Please Do like this

fChoices = new ArrayList<>() ;

    rm.getAllCourses(new VolleyCallbackOp() {
        public void onSuccess4(List<Course> cl) {
            String [] choices = new String[cl.size()];
            for (int a = 0; a < cl.size(); a++) {
                Course c = cl.get(a);
                fChoices.add(c.toString());
                choices[a] = c.toString();
            }

        }
    });

Change this-:

ArrayAdapter<String> aa = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, choices)

To-:

ArrayAdapter<Course> aa = new ArrayAdapter<Course>(this, android.R.layout.simple_spinner_item, choices)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM