Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
488 views
in Technique[技术] by (71.8m points)

java - Using volley library, inside the onResponse Method the ArrayList have some data but outside the OnResponse method the arraylist is empty

I am doing the network operation in a model and then return the result, but the arraylist size is zero when I return it but inside the onResponse method the arraylist size is not zero. How to resolve this?

      public class doInBackground {

           //i have initialized the arraylist here 
            ArrayList<Contact> arrayList=new ArrayList<>();
            String url="http://192.168.10.3/volley/allUser.php"; 
            private Context context;
            public doInBackground(Context context){
                this.context=context;
            }

            public ArrayList<Contact> getArrayList(){
                JsonArrayRequest jsonArrayRequest=new JsonArrayRequest(Request.Method.POST, url, null, new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {

                        for(int i=0;i<response.length();i++){
                            try {
                                JSONObject jsonObject=response.getJSONObject(i);
                                Contact contact=new Contact();
                                contact.setName(jsonObject.getString("name"));
                                contact.setUserName(jsonObject.getString("username"));
                                arrayList.add(contact);
                            } catch (JSONException e) {
                                e.printStackTrace();
                                Toast.makeText(context,e.toString(),Toast.LENGTH_LONG).show();
                            }
                        }

//outside the for loop the arraylist have data( i.e fetch from Mysql database)
                    }

                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Toast.makeText(context,error.toString(),Toast.LENGTH_LONG).show();
                    }
                });
                Toast.makeText(context,arrayList.size()+"",Toast.LENGTH_LONG).show();

           //using singleton design pattern to add the request to the queue                    MySingleton.getInstance(context).addToRequestQueue(jsonArrayRequest);
           // here the arraylist is empty

                    return arrayList;
                }


        }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It is tipical not understanding async operations, Listener which You have given to Volley is waiting for response and Your return statement is called not when response returns from server side, but is called instantly. It means Your arrayList is just empty ( code which fills it is running after response come back ). It must be async operations because if not all UI thread for user would just stop and Your application would not respond for any user action.

So to fix this problem You need to wait until response will return and then after filling array call next wanted flow. Good is to add some loader view, show it before starting of request and hide after end of request.

Maybe some flow comparission.

Current flow:

  • start of volley request
  • return arrayList ( empty list )
  • volley response is filling arrayList

Wanted flow:

  • show loader
  • start of volley request
  • volley response is filling arrayList
  • hide loader
  • call wanted action after response with ready to use arrayList

EDIT ( about loader )

For loading can be used any view ( for example simple view with image ) by using view properties like VISIBILITY, so when loader view should be visible just call loaderView.setVisibility(View.VISIBLE) and when should be hidden - loaderView.setVisibility(View.GONE).

To this purpose also can be used one of ready to use android libraries like ContentLoadingProgressBar.


Example usage of ContentLoadingProgressBar.

First add it to layout:

<android.support.v4.widget.ContentLoadingProgressBar
    android:id="@+id/loader"
    style="?android:attr/progressBarStyleLarge"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:visibility="gone" />

Next in Activity find it by:

ContentLoadingProgressBar loader = (ContentLoadingProgressBar)findViewById(R.id.loader);

And last just use it, for showing loader.show(), for hidding loader.hide(). So back to main point - show before request, hide inside in response listener.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...