android - 从不同的线程修改 View

标签 android multithreading android-listview progressdialog

我从服务器获取一个 JSON,它是我的 ListView 的内容。 一切都很好,但我想在调用 Json 时创建一个 ProgressDialog。 问题是我需要在不同的线程中调用 JSON(使用 http 方法)并在 ListView 中向用户显示结果。

这是我正在做的事情,但出现错误 "05-09 12:13:28.358: W/System.err(344): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created View 层次结构可以触及它的 View 。”

try {       
            final ProgressDialog progDailog;
            progDailog =ProgressDialog.show(this,"HI", "Loading");

            new Thread(new Runnable() {

                @Override
                public void run() {
                    try 
                    {
                        JSONArray json = new JSONArray(executeHttpGet("http://m-devsnbp.insightlabs.cl/cuentos/json"));
                        progDailog.cancel();
                        ArrayList<HashMap<String, String>> talesList = new ArrayList<HashMap<String, String>>();
                        talesList = jsonToHash(json);
                        adapter = new LazyAdapter((Activity) ctx, talesList, 2);    
                        list.setAdapter(adapter);
                    } 
                    catch (InterruptedException e) 
                    {
                        e.printStackTrace();
                    } catch (JSONException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }   
                }
            }).start();

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

如何从不同的线程更新我的观点?还是更好的方法?

最佳答案

您需要在主 ui 线程上更新 ui。使用 runOnUiThread

        runOnUiThread(new Runnable() //run on ui thread
                 {
                  public void run() 
                  { 
                    progDailog.cancel(); 
                    adapter = new LazyAdapter((Activity) ctx, talesList, 2);    
                    list.setAdapter(adapter);   
                  }
                 });

也可以考虑使用异步任务。我建议 ypu 使用 asynctask

http://developer.android.com/reference/android/os/AsyncTask.html

        ProgressDialog pd; 
        LazyAdapter adapter;  
        ListView list; 
        ArrayList<HashMap<String, String>> talesList = new ArrayList<HashMap<String, String>>();  

在你的 onCreate() Activity 中

        pd = new ProgressDialog(ActivityName.this);
        pd.setTitle("Processing..."); 
        new TheTask().execute(); 

将 AsyncTask 定义为 Activity 类中的内部类

    class extends AsyncTask<Void,Void,Void>
    {
    @Override
protected void onPreExecute() {
   // TODO Auto-generated method stub
      super.onPreExecute();
      pd.show();
          
}

@Override
protected Void doInBackground(Void... params) {
    // TODO Auto-generated method stub
                 try 
                {
                    JSONArray json = new JSONArray(executeHttpGet("http://m-devsnbp.insightlabs.cl/cuentos/json"));
                    talesList = jsonToHash(json);
                    
                } 
                catch (InterruptedException e) 
                {
                    e.printStackTrace();
                } catch (JSONException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }   
    return null;
             
}
    
    @Override
protected void onPostExecute(Void result) {
    // TODO Auto-generated method stub
    super.onPostExecute(result);
            pd.dismiss();
            adapter = new LazyAdapter(AcctivityName.this, talesList, 2);    
            list.setAdapter(adapter); 
}  
    }

2021 年 1 月更新

上面的答案已经过时(asynctask 已被删除)。还有其他更新 ui 的新方法。根据您使用协程还是 rxjava,您可以轻松更新 ui。在这种情况下最好问一个新问题。

关于android - 从不同的线程修改 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16466521/

相关文章:

multithreading - 使用并行排序和多个字段对列表进行排序

c# - 在ConcurrentQueue中入队和TryDequeue

添加新项目时调用 Requery 后,带有 CursorAdapter 的 Android ListView 的滚动位置不正确

java - 过滤同一个ListView中的两个字符串

java - 在 ArrayList 中计数时跳过元素

测试 Android 应用程序进程生命周期并在达到空进程状态时恢复状态

java - 使用 XML 字符串

c# - 在 C# 中并行读取具有一百万行的 csv 文件

java - 为所有应用程序 ListView android添加点击功能

android - 如何保持 ExpandableListView 打开?