从其他线程修改视图

时间:2013-05-09 16:25:10

标签: 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 a view hierarchy can touch its views."

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();
        }

如何从其他主题更新我的观点?或者这是一个更好的方法吗?

4 个答案:

答案 0 :(得分:3)

您需要在主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);   
                  }
                 });

还要考虑使用asynctask。我建议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()

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

将AsyncTask定义为活动类中的内部类

    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); 
}  
    }

答案 1 :(得分:0)

当您尝试从非UI线程更新视图时,需要通过post()方法更新它:

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

            Thread mThread = 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();
                    }   
                }
            });

            post(mThread);

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

答案 2 :(得分:0)

Modyfing Views只能在UI Thread上进行,所以对我来说,你应该尝试使用一个处理Activity引用的类并传递runnable来运行

class UIUpdater{
private static UIUpdater mInstance;
private Activity mActivity;
    public static UIUpdater getInstance()
    {
        if(mInstance == null){
            mInstance = new UIUpdater();
        }
        return mInstance;
    }

    public void runOnUiThread(Runnable run){
        mActivity.runOnUiThread(run);
    }
} 

另一种方法是使用Loopers: 例如

Looper mMainLooper = Looper.getMainLooper();

有关详细信息,请参阅here

答案 3 :(得分:0)

我认为有更好的方法可以做到这一点。就像使用AsyncTask

一样

这只是您想要做的代码示例。

private class LongOperation extends AsyncTask<Void, Void, Void> {

  private ProgressDialog progressDialog;
  private ArrayList<HashMap<String, String>> talesList;
  private LazyAdapter adapter;
  private Context mContext;

  public LongOperation(Context c) {
    mContext = c;
    progressDialog = new ProgressDialog(c);
  }

  @Override
  protected void onPreExecute() {
    //operation start, show the dialog
    progressDialog.show();
  }

  @Override
  protected String doInBackground(Void... params) {
    //connect to server and get json
    try 
    {
      JSONArray json = new JSONArray(executeHttpGet("http://m-devsnbp.insightlabs.cl/cuentos/json"));
      talesList = new ArrayList<HashMap<String, String>>();
      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();
    }   
  }      

  @Override
  protected void onPostExecute(Void result) {
    //operation end, dismiss the dialog and set result to list
    progressDialog.dismiss();
    adapter = new LazyAdapter(mContext, talesList, 2);    
    list.setAdapter(adapter);
  }

}

您可能想看一些链接:

AsyncTask Android Example

Understanding AsyncTask