初始化一个ArrayList,以异步方式获取另一个ArrayList。

huangapple go评论77阅读模式
英文:

Initialize ArrayList to ArrayList obtained asynchronously

问题

以下是翻译好的部分:

我正在尝试创建一个新的ArrayList实例并将其初始化为由函数返回的ArrayList到目前为止我尝试过的方法都不起作用

这是我的函数它应该返回一个类型为<User>的ArrayList我已经测试过它它完美地工作内容被成功读取并存储在函数内部创建的临时ArrayList中在填充了这个ArrayList之后函数将返回它

    public ArrayList<User> fetchAllUsers() {

       final ArrayList<User> allUsers = new ArrayList<>();

        RequestQueue requestQueue = Volley.newRequestQueue(this);
        JsonArrayRequest arrayRequest = new JsonArrayRequest(
                Request.Method.GET,
                "http://ecoproduce.eu/api/User",
                null,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        Log.e("Rest response", response.toString());

                        Gson gson = new Gson();
                        User user = new User();

                        for (int i = 0; i < response.length(); i++) {
                            try {
                                user = gson.fromJson(response.getJSONObject(i).toString(), User.class);
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                            allUsers.add(user);
                        }

                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Log.e("Error response", error.toString());
                    }
                }
        );
        requestQueue.add(arrayRequest);
        return allUsers;
    }

我面临的问题是当我尝试声明一个新的ArrayList实例并尝试用从函数返回的ArrayList填充它时

我尝试过以下方式

通过构造函数初始化新创建的实例

    ArrayList<User> allUsers = new ArrayList<User>(fetchAllUsers()); 

通过addAll()函数初始化新创建的ArrayList的实例

    ArrayList<User> allUsers = new ArrayList<User>();
    allUsers.addAll(fetchAllUsers());

这两种尝试都使我得到了一个空的ArrayList我该如何解决这个问题

解决方法

实现一个接口

    public interface VolleyCallBack {
        ArrayList<User> onSuccess();
    }

对getAllUsers函数的更改

     public ArrayList<User> getAllUsers(final String email, final VolleyCallBack callBack) {


        requestQueue = Volley.newRequestQueue(this);
        JsonArrayRequest arrayRequest = new JsonArrayRequest(
                Request.Method.GET,
                "http://ecoproduce.eu/api/User",
                null,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        Log.e("Rest response", response.toString());

                        Gson gson = new Gson();
                        User user = new User();

                        for (int i = 0; i < response.length(); i++) {
                            try {
                                user = gson.fromJson(response.getJSONObject(i).toString(), User.class);
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                            allUsers.add(user);
                        }
                        /*for (int i = 0; i < allUsers.size(); i++) {
                            if (allUsers.get(i).getEmail().compareTo(email) == 0) {
                                checkSucesfull = true;
                            }

                        }*/
                        callBack.onSuccess();
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Log.e("Error response", error.toString());
                    }
                }
        );
        requestQueue.add(arrayRequest);
        return allUsers;
    }

现在如何调用函数

    allUsers = getAllUsers(email, new VolleyCallBack() {
                        @Override
                        public ArrayList<User> onSuccess() {
                            return allUsers;
                        }
                    });


并且allUsers ArrayList被声明为全局变量这可能不是最佳解决方案)。

我仍然可以接受对此的改进意见
英文:

I am trying to create a new ArrayList instance and initialize it to an arraylist returned by a function. The things I have tried so far do not work.

This is my function which is supposed to return an ArrayList of type <User>. I have tested it and it works perfectly, the contents are read successfully and are stored in the temporary ArrayList created within the function. After filling this ArrayList the function will return it.

public ArrayList&lt;User&gt; fetchAllUsers() {
final ArrayList&lt;User&gt; allUsers = new ArrayList&lt;&gt;();
RequestQueue requestQueue = Volley.newRequestQueue(this);
JsonArrayRequest arrayRequest = new JsonArrayRequest(
Request.Method.GET,
&quot;http://ecoproduce.eu/api/User&quot;,
null,
new Response.Listener&lt;JSONArray&gt;() {
@Override
public void onResponse(JSONArray response) {
Log.e(&quot;Rest response&quot;, response.toString());
Gson gson = new Gson();
User user = new User();
for (int i = 0; i &lt; response.length(); i++) {
try {
user = gson.fromJson(response.getJSONObject(i).toString(), User.class);
} catch (JSONException e) {
e.printStackTrace();
}
allUsers.add(user);
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(&quot;Error response&quot;, error.toString());
}
}
);
requestQueue.add(arrayRequest);
return allUsers;
}

The problem I face is when I try to declare a new arrayList instance and I try to fill it with the ArrayList returned from the function.

I have tried doing this in the following ways:

Initialize the newly created instance through the constructor:

ArrayList&lt;User&gt; allUsers = new ArrayList&lt;User&gt;(fetchAllUsers()); 

Initialize the newly created instace of ArrayList through the addAll() function

ArrayList&lt;User&gt; allUsers = new ArrayList&lt;User&gt;();
allUsers.addAll(fetchAllUsers());

Both of these attempts have left me with an empty ArrayList, how can I solve this?

SOLUTION:

Implemented an interface

public interface VolleyCallBack {
ArrayList&lt;User&gt; onSuccess();
}

Changes to the getAllUsers function

 public ArrayList&lt;User&gt; getAllUsers(final String email, final VolleyCallBack callBack) {
requestQueue = Volley.newRequestQueue(this);
JsonArrayRequest arrayRequest = new JsonArrayRequest(
Request.Method.GET,
&quot;http://ecoproduce.eu/api/User&quot;,
null,
new Response.Listener&lt;JSONArray&gt;() {
@Override
public void onResponse(JSONArray response) {
Log.e(&quot;Rest response&quot;, response.toString());
Gson gson = new Gson();
User user = new User();
for (int i = 0; i &lt; response.length(); i++) {
try {
user = gson.fromJson(response.getJSONObject(i).toString(), User.class);
} catch (JSONException e) {
e.printStackTrace();
}
allUsers.add(user);
}
/*for (int i = 0; i &lt; allUsers.size(); i++) {
if (allUsers.get(i).getEmail().compareTo(email) == 0) {
checkSucesfull = true;
}
}*/
callBack.onSuccess();
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(&quot;Error response&quot;, error.toString());
}
}
);
requestQueue.add(arrayRequest);
return allUsers;
}

How I call the function now

allUsers = getAllUsers(email, new VolleyCallBack() {
@Override
public ArrayList&lt;User&gt; onSuccess() {
return allUsers;
}
});

And the allUsers ArrayList is made global (which is probably not the best solution).

I am still open to improvements on this.

答案1

得分: 1

我理解的是,您正在进行一个异步调用以获取列表项。这些项将在稍后的某个时候到达,但初始化将在函数被调用时立即发生。您的ArrayList是同步的,方法**fetchAllUsers()**会在后台线程中调用一个API来填充ArrayList中的项,但会立即返回一个空列表,这就是您为什么会得到空列表。

因此,实际上您不能初始化某些依赖于后台线程的ArrayList。您可以使用回调来稍后获取数据,但不能立即获取,我希望您能理解我的意思。

现在该怎么办:
取决于您想实现什么,但只需从fetchAllUsers中不返回任何内容,在api调用的回调中执行您想要的操作。

public void fetchAllUsers() {
    final ArrayList<User> allUsers = new ArrayList<>();
    RequestQueue requestQueue = Volley.newRequestQueue(this);
    JsonArrayRequest arrayRequest = new JsonArrayRequest(
            Request.Method.GET,
            "http://ecoproduce.eu/api/User",
            null,
            new Response.Listener<JSONArray>() {
                @Override
                public void onResponse(JSONArray response) {
                    Log.e("Rest response", response.toString());

                    Gson gson = new Gson();
                    User user = new User();

                    for (int i = 0; i < response.length(); i++) {
                        try {
                            user = gson.fromJson(response.getJSONObject(i).toString(), User.class);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                        allUsers.add(user);
                    }
                   //在这里,您的列表项已经准备好使用了,所以调用某个函数来使用它
                  //TODO 调用进一步的函数
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Log.e("Error response", error.toString());
                }
            }
    );
    requestQueue.add(arrayRequest);
}
英文:

What I am getting is you are making an asynchronous call to get the list items. which will come sometime later but the initialization will happen as soon as the function gets called. Your ArrayList is in synchronous and the method fetchAllUsers() calls for an API to in background thread to fill the items in ArrayList but returns an empty list instantly that's why you are getting empty list.

So in actual you can't initialize some ArrayList which depends on the background thread. you can use callbacks to get the data later but not instantly i hope you are getting my point.

Now what to do:
Depends on what you are trying to achieve but just return nothing from fetchAllUsers and on callback of api call do whatever you want to do

   public void fetchAllUsers() {
final ArrayList&lt;User&gt; allUsers = new ArrayList&lt;&gt;();
RequestQueue requestQueue = Volley.newRequestQueue(this);
JsonArrayRequest arrayRequest = new JsonArrayRequest(
Request.Method.GET,
&quot;http://ecoproduce.eu/api/User&quot;,
null,
new Response.Listener&lt;JSONArray&gt;() {
@Override
public void onResponse(JSONArray response) {
Log.e(&quot;Rest response&quot;, response.toString());
Gson gson = new Gson();
User user = new User();
for (int i = 0; i &lt; response.length(); i++) {
try {
user = gson.fromJson(response.getJSONObject(i).toString(), User.class);
} catch (JSONException e) {
e.printStackTrace();
}
allUsers.add(user);
}
//here your list items are ready to be used, so call some function to consume it 
//TODO call to further function
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(&quot;Error response&quot;, error.toString());
}
}
);
requestQueue.add(arrayRequest);
}

答案2

得分: 0

以下是使用等待和通知进行修复的代码。这应该能够正常工作,因为在返回之前的等待调用只会在 JsonArrayRequest 的 onResponse 中的通知调用之后继续执行。

public ArrayList<User> fetchAllUsers() {

   final ArrayList<User> allUsers = new ArrayList<>();
   final Object notifyObj = new Object();
    RequestQueue requestQueue = Volley.newRequestQueue(this);
    JsonArrayRequest arrayRequest = new JsonArrayRequest(
            Request.Method.GET,
            "http://ecoproduce.eu/api/User",
            null,
            new Response.Listener<JSONArray>() {
                @Override
                public void onResponse(JSONArray response) {
                    Log.e("Rest response", response.toString());

                    Gson gson = new Gson();
                    User user = new User();

                    for (int i = 0; i < response.length(); i++) {
                        try {
                            user = gson.fromJson(response.getJSONObject(i).toString(), User.class);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                        allUsers.add(user);
                    }
                    synchronized (notifyObj) {
                      notifyObj.notifyAll();
                    }

                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    Log.e("Error response", error.toString());
                }
            }
    );
    requestQueue.add(arrayRequest);
    synchronized (notifyObj) {
      notifyObj.wait();
    }
    return allUsers;
}
英文:

Here's a fix using wait and notify. This should work, as the wait call before returning will only proceed after the notify call in the JsonArrayRequest onResponse

public ArrayList&lt;User&gt; fetchAllUsers() {
final ArrayList&lt;User&gt; allUsers = new ArrayList&lt;&gt;();
final Object notifyObj = new Object();
RequestQueue requestQueue = Volley.newRequestQueue(this);
JsonArrayRequest arrayRequest = new JsonArrayRequest(
Request.Method.GET,
&quot;http://ecoproduce.eu/api/User&quot;,
null,
new Response.Listener&lt;JSONArray&gt;() {
@Override
public void onResponse(JSONArray response) {
Log.e(&quot;Rest response&quot;, response.toString());
Gson gson = new Gson();
User user = new User();
for (int i = 0; i &lt; response.length(); i++) {
try {
user = gson.fromJson(response.getJSONObject(i).toString(), User.class);
} catch (JSONException e) {
e.printStackTrace();
}
allUsers.add(user);
}
sychronized(notifyObj) {
notifyObj.notifyAll();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(&quot;Error response&quot;, error.toString());
}
}
);
requestQueue.add(arrayRequest);
synchronized(notifyObj) {
notifyObj.wait();
}
return allUsers;
}

huangapple
  • 本文由 发表于 2020年3月4日 02:49:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/60513761.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定