本文介绍了Android Volley如何同步Listener.onRespone()中的数据以便在onRespone()之外使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要从Internet服务器读取数据并通过ListView在MainActivity中显示它.我决定使用Volley lib来获取数据.在阅读了数小时的stackoverflow之后,我已经实现了使用回调通过Volley lib从JSONArray提取数据.我的代码如下

I need to read data from a internet server and display it in MainActivity via ListView. I've decided to use Volley lib to get data.After reading stackoverflow for hours I've achieved to extract data from JSONArray via Volley lib using callback.My code is follows

public class DownloadsManager
{
    public interface VolleyCallback
    {
        void onSuccess(JSONArray result);
    }

    public static void getVolleyResponse(String url, Context ctx, final VolleyCallback callback)
    {
        RequestQueue requestQueue  = Volley.newRequestQueue(ctx);
        JsonArrayRequest request = new JsonArrayRequest(Request.Method.GET, url, null,
                new Response.Listener<JSONArray>()
                {
                    @Override
                    public void onResponse(JSONArray response)
                    {
                       callback.onSuccess(response);
                    }
                },
                new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error)
                {
                    // TODO
                }
                 });
        requestQueue.add(request);
    } 
}

在这里,我将JSONArray解析为MyObject Java对象

Here I parse JSONArray into MyObject Java object

public class JSONParser
{
    public static ArrayList <MyObject> parseJSONresponse (JSONArray response)
    {
        ArrayList<Object> list = new ArrayList<>();

        try {
            JSONArray array = response;

            for (int i=0; i<array.length(); i++)
            {
                JSONObject object = array.getJSONObject(i);
                MyObject obj = new Object();

                //Object's string name
                channel.setName(object.getString("name"));

                list.add(channel);
            }
        } catch (Exception e)
        { e.printStackTrace();}

        return list;
    }
}

以上所有方法均有效,并在通过Debug检查后​​给出了正确的价值

在MainActivity中发生了一些我不了解的魔术.请注意onSuccess(),在这里我解析JSONArray,将值分配给ArrayList列表,并创建ArrayAdapter和ListView:

And in MainActivity happens some magic, what I don't understand.Please, pay attention to onSuccess(), where I parse JSONArray, assign value to ArrayList list, and create ArrayAdapter and ListView :

    public class MainActivity extends AppCompatActivity
    {
        private static final String URL = "http://someurl/json";
        private ListView listView;
        private ArrayList <MyObject> list;

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

            listView = (ListView) findViewById(R.id.mainlistview);

            DownloadsManager.getVolleyResponse(URL, getApplicationContext(),
                    new DownloadsManager.VolleyCallback()
                    {

                        public void onSuccess(JSONArray result)
                        {
                          list.addAll(JSONParser.parseJSONresponse(result)); 
                            ArrayAdapter <String> adapter = 
                                new ArrayAdapter <>(MainActivity.this, R.layout.channel_item_layout,list);
                            listView.setAdapter(adapter);
                        }
                    });
        }
    }

但是当我尝试使用ArrayList列表时,结果发现该列表在离开onSuccess()之后失去了它的值:

But when I try to use ArrayList list, it turn's out that list lost its value after leaving onSuccess():

Toast.makeText(this, list.get(0).getName(), Toast.LONG).show();
//output error, list.size() == 0, impossible to invoke list.get(0).getName()

从onSuccess返回后的

ArrayList列表给出size()== 0,但是在onSuccess内部它工作良好.
问题1:我想在下一个方法中使用ArrayList列表的值,如何将onSuccess中的值初始化为ArrayList列表并在程序中进一步使用此列表?
问题2:为什么会发生?

ArrayList list after returning from onSuccess gives size() == 0, but inside onSuccess it works well.
QUESTION-1: I want to use ArrayList list's values in some next methods, how I can initialize value from onSuccess into ArrayList list and use this list further in my program?
QUESTION-2: Why it happens?

更新:正如Gabe Sechan指出的关于异步的问题一样,如何在onSuccess()内的JSONArray上使用Java同步关键字来使用onSuccess()范围之外的值?

UPDATED: as Gabe Sechan point me about asynchronisation, how I can use Java synchronized keyword on JSONArray inside onSuccess() for to use values outside scopes of onSuccess()?

推荐答案

因为Volley与所有网络结果一样都是异步的.它与程序同时在另一个线程上发生.然后,它再次在主线程上运行最终的回调(onSuccess或onFailure).您要检查列表大小的调用是在主线程上发出的,但它是在Volley完成之前发出的(对于一个小的请求,它可能需要一秒钟左右,对于一个大的请求,可能需要几秒钟).由于Volley尚未完成,因此列表为空.

Because Volley, like all network results, is asynchronous. It happens on another thread, at the same time as your program. It then runs the final callbacks (onSuccess or onFailure) on the main thread again. Your call to check the size of the list comes on the main thread, but it comes before Volley is finished (which will likely take a second or so for a small request, a few seconds for a big one). Since Volley isn't finished yet, the list is empty.

您的代码对于初始化列表将是正确的.在Volley准备好之前,您无法使用它.这意味着所有需要填充列表的代码都必须在onSuccess中发生,或者直到onSuccess之后才被调用.

Your code would have been just fine for initializing the list. You just can't use it until Volley is ready. That means ALL of the code that requires the list to be filled must occur in onSuccess, or not be called until after onSuccess is.

这篇关于Android Volley如何同步Listener.onRespone()中的数据以便在onRespone()之外使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-23 15:34