【问题标题】:Android ListView and multiple threads that updates the listviewAndroid ListView 和更新列表视图的多个线程
【发布时间】:2012-07-13 12:30:25
【问题描述】:

我有一个活动,其中一个列表视图显示项目。这个活动有三个按钮和一个带有多个其他按钮的菜单。

当我按下一个按钮时,会启动一个新线程,从 Web 服务获取数据,填充列表视图。然后显示列表视图。

唯一的问题是每次我按下一个按钮时,我都会启动一个线程。根据检索数据所需的时间,有时会发生列表视图未填充好的数据(用户不等待一个线程完成并按下另一个按钮)

首先我尝试取消线程,但它不起作用(异步任务或使用 thread.interrupt)

我怎样才能停止以前的线程,以便列表视图将被最后的数据填充?

感谢您的帮助:)

// Items to be displayed in the listview
    private ArrayList<HashMap<String, Object>> oItems = new ArrayList<HashMap<String, Object>>();

    // Launch the thread when toggle is checked
    button.setOnCheckedChangeListener(new OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView,
                boolean isChecked) {
            if (isChecked) {
                LoadListView();
            }

        }
    }); 

oMenu.setOnChildClickListener(new OnChildClickListener() {

            @Override
            public boolean onChildClick(ExpandableListView parent, View v,
                    int groupPosition, int childPosition, long id) {
                LoadListView();
                return true;
            }

        });

    private void LoadListView() {   
        new Thread(ListViewRunnable).start();
    }

    private Runnable ListViewRunnable = new Runnable() {
        public void run() {
            while (GetItems() < 1) {    
            }

            MainHandler.post(new Runnable() {
                public void run() {

                }
            });
        }

        private int GetItems() {
            try {
                HashMap<String, Object> oItem;

                //Get items from web services
                List<ItemFromService> oItemsFromService = GetItemsFromWebService();

                for (oItemFromService : oItemsFromService) {
                    oItem = new HashMap<String, Object>();
                    oItem.put("ID", oItemFromService.get_iID());
                    oItem.put("Label", oItemFromService.get_sLabel());

                    oItems.add(oItem);
                }

                MainHandler.sendEmptyMessage(GOT_ITEMS);

            } catch (Exception e) {

            }

            return 1;
        }
    }

    private Handler MainHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {

            if (msg.what == GOT_ITEMS) {

                adapter.notifyDataSetChanged();
            }
        }
    };

【问题讨论】:

  • 您是否使用 Thread 或 AsyncTask 或其他工具来生成线程?一些示例代码可能会有所帮助。
  • 列出您正在使用的一些代码,以便于理解。
  • 我正在使用可运行的线程。我的线程连接到 Web 服务,用对象填充数组,然后调用 .notifyDataSetChanged() 方法来刷新列表视图。

标签: android multithreading listview android-activity


【解决方案1】:

在获得完整所需数据之前,不要使用adaptername.notifyDataSetChanged()方法,这样ListView的适配器不会被更新,旧数据会被持久化。

【讨论】:

  • 好的,但是当新线程启动时,我如何对旧线程说他们不必执行 notifyDataSetChanged() 方法? :)
  • 布尔值通常用于线程知道他们需要继续运行.. 很多时候线程将使用 while(mRunning) {..do work..}。
  • 您是否为所有不同的按钮单击创建了不同的异步方法?在我们的例子中..3个按钮所以3个异步方法??
  • 我尝试使用 volatile 布尔值并更改其值以指示它们必须停止的旧线程,但仍显示项目(似乎线程没有看到布尔值的变化)
  • 我认为主要问题是所有线程都在填充 ArrayList> 列表。但是我有很多按钮(可能是 20 个)可以启动列表视图的刷新......所以我真的不想创建 20 个列表和 20 个列表视图
【解决方案2】:

您可以使用 Thread 类代替 AsyncTask。实例化 Thread 并维护它的句柄。使用:

hThread.interrupt()

向线程发送中断消息,并在线程内部进行测试:

if (isInterrupted())
 return;

离开话题。

【讨论】:

  • 好的,我会试试的。我试图将我的线程放在一个列表中,在启动一个新线程之前,我试图中断线程,但没有在线程中检查方法“isInterrupted”。当您的意思是“维护句柄”时,它可以是一个带有线程的数组列表,对吗?谢谢
  • 是的,hThread = new Thread(...),将它存储在 ArrayList 或其他任何东西中。您还可以使用 thread.isAlive() 来测试线程当前是否正在运行。线程结束后,您需要将其从列表中删除。
  • 好的,我会试试看,如果可以的话告诉你:) 谢谢
  • 似乎不起作用。我有一个线程数组列表和一个私有全局线程。每次单击按钮时,我都会遍历线程,调用中断方法,清除数组列表并调用新线程。在可运行文件中,当我的对象从我的网络服务中检索时,我检查了线程是否已被中断。我的列表视图仍然使用不同的数据刷新多次,并且线程似乎没有中断。我不明白我做错了什么:(
  • private ArrayList&lt;Thread&gt; oThreads; private Thread oAnnonceThread;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多