Using volley library, inside the onResponse Method

2020-01-29 02:00发布

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;
                }


        }

1条回答
够拽才男人
2楼-- · 2020-01-29 02:25

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.

查看更多
登录 后发表回答