简体   繁体   English

如何在完成之前从AsyncTask更新ListView

[英]How to update a ListView from an AsyncTask before it completes

I have a client application that uses sockets and input/output stream to communicate with a server and ask for some data. 我有一个使用套接字和输入/输出流与服务器通信并请求一些数据的客户端应用程序。 I've created an AsyncTask and on doInBackground() of it I make the connection and send/receive data. 我创建了一个AsyncTask,并在其doInBackground()上进行连接并发送/接收数据。
doInBackground(): doInBackground():

@Override
        protected Object doInBackground(Object... objIn) {

            // we create a TCPClient object and
            client = new T_Client(new T_Client.OnMessageReceived() {
                @Override
                // here the messageReceived method is implemented
                public void messageReceived(Object objIn) {
                    Log.v(tagTask, "Object Received: " + objIn);                        
                        Log.w(tagTask, "Object returned: " + objIn);
                        mapReturn = (Map<String, Integer>) objIn;
                        Log.i(tagTask, "Map Object Returned: " + mapReturn);
                        onProgressUpdate();                     
                }
            });
            client.run();

            return objIn;
        }

User is a simple class to help me process the data I get from the server. 用户是一个简单的类,可以帮助我处理从服务器获取的数据。 I get a Map from the server as a "Users List",which I want to display in a ListView on my Main Activity, with Username(String) and OnLine status(Integer) and I pass it to a local Map object. 我从服务器以“用户列表”的形式获取地图,该地图要显示在Main Activity的ListView中,并带有Username(String)和OnLine status(Integer),并将其传递给本地Map对象。 Then I call the onProgressUpdate() method of my AsyncTask. 然后,我调用AsyncTask的onProgressUpdate()方法。
onProgressUpdate(): onProgressUpdate():

@Override
        protected void onProgressUpdate(Void... voids) {
            super.onProgressUpdate();

            for (Entry<String, Integer> entry : mapReturn.entrySet()) {
                if (entry.getValue() == 1) {
                    User user = new User(entry.getKey(), "YES");
                    Log.v(tagTask, "UserName: " + user.getUser());
                    Log.v(tagTask, "Online Status : " + user.getOnLine());
                    listUsers.add(user);
                } else if (entry.getValue() == 0) {
                    User user = new User(entry.getKey(), "NO");
                    Log.v(tagTask, "UserName: " + user.getUser());
                    Log.v(tagTask, "Online Status : " + user.getOnLine());
                    listUsers.add(user);
                }
            }

             mAdapter.notifyDataSetChanged();
        }

    }

In here, I iterate through the Map object's entries and for each entry I create a User object and then add the user object to my ArrayList "listUsers", which is the array list I use for my ListView's adapter. 在这里,我遍历Map对象的条目,并为每个条目创建一个User对象,然后将该用户对象添加到ArrayList“ listUsers”,这是我用于ListView适配器的数组列表。 Now when I run the mAdapter.notifyDataSetChanged() of course I get an error because I'm trying to update my main UI, not from the main UI thread. 现在,当我运行mAdapter.notifyDataSetChanged()时,我当然会收到错误消息,因为我正在尝试更新主UI,而不是从主UI线程进行更新。 The reason that I can't use the onPostExecute() method is because I keep doInBackground() running(client.run()). 之所以不能使用onPostExecute()方法,是因为我一直在运行doInBackground()(client.run())。 And the reason I do that is because I have to keep the connection between the server and the client alive so that I can ask for data from the server and the server to send those data. 之所以这样做,是因为我必须保持服务器与客户端之间的连接处于活动状态,以便可以从服务器和服务器请求数据以发送这些数据。

So I'm asking you guys if there is a way to update my ListView before the AsyncTask completes(which in this case, it'll never get to onPostExecute); 所以我问你们是否有一种方法可以在AsyncTask完成之前更新我的ListView(在这种情况下,它将永远无法到达onPostExecute);

PS I've noticed something strange that I can't explain. 附言:我注意到我无法解释的奇怪之处。 When I tap on an EditText that I have in my activity, and the keyboard pops up, the ListView updates and I can see my data. 当我点击活动中的EditText并弹出键盘时,ListView更新,并且我可以看到我的数据。

The reason that I can't use the onPostExecute() method is because I keep doInBackground() running(client.run()). 之所以不能使用onPostExecute()方法,是因为我一直在运行doInBackground()(client.run())。

IMHO, that is an inappropriate use of AsyncTask . 恕我直言,这是AsyncTask的不当使用。 Do not tie up a resource from a resource pool indefinitely, when you are not the one who create and manage the pool. 当您不是创建和管理该池的人时,请不要无限期地占用资源池中的资源。

Instead, create your own thread. 而是创建您自己的线程。 Then use Handler to pass messages to code of yours that runs on the main application thread, to update your list. 然后使用Handler将消息传递给在主应用程序线程上运行的代码,以更新列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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