android.view.viewrootimpl $ calledfromwrongthreadexception android java

时间:2014-11-28 06:30:27

标签: java android list listview

我声明了一个界面:

public interface GetChildList{
        public void onGetChildList(List<String> list);
}

在我的班级(我称之为fetchJSONChild())中实施:

import com.example.hakslogin.GetChildList;

public class ChildActivity extends ActionBarActivity implements GetChildList {

    Button btn_home;
    Button btn_add;
    private HandleJSON obj;
    public String urlString = "http://192.168.x.xx:xxxx/getdb";

    List<String> child = new ArrayList<String>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_child);


        obj = new HandleJSON(urlString);
        child = obj.fetchJSONChild(this);
    }

    @Override
    public void onGetChildList(List<String> list) {
       //this method will be called after thread in fetchJSONChild ended
       child = list;
       //here you can work with your list

    }
}

以下是我的fetchJSONChild

public void fetchJSONChild(final GetChildList callBack){

        final List<String> child = new ArrayList<String>();
        Thread thread = new Thread(new Runnable(){

            @Override
            public void run() {

                try {

                    URL url = new URL("http://192.168.x.xx:xxxx/childform_list/0.0.0.0/8069/new_db/admin/123456");
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setReadTimeout(30000 /* milliseconds */);
                    conn.setConnectTimeout(50000 /* milliseconds */);
                    conn.setRequestMethod("GET");
                    //conn.setRequestProperty("User-Agent", "GYUserAgentAndroid");
                    conn.setRequestProperty("Content-Type", "application/json");
                    conn.setDoInput(true);
                    //conn.setUseCaches (false);
                    // Starts the query
                    if (Build.VERSION.SDK != null && Build.VERSION.SDK_INT > 13) {

                        conn.setRequestProperty("Connection", "close"); 
                    }
                    conn.connect();

                    System.out.println("Before url.openStream()");
                    InputStream stream = conn.getInputStream();//.openStream();
                    System.out.println("After url.openStream()");
                    String data = convertStreamToString(stream);
                    // for examole data = "1,2,3";

                    child.addAll(Arrays.asList(data.split(","));
                    readAndParseJSON(data);
                    stream.close();

                    callBack.onGetChildList(child);
                } catch (Exception e) {

                    e.printStackTrace();
                }
            }
        });
        thread.start(); 
    }

一切正常,我在ChildActivity onGetChildList方法中获取列表。

但我想在list中填充listview,如下所示:

@Override
public void onGetChildList(List<String> list) {
   //this method will be called after thread in fetchJSONChild ended
    List<String> array = new ArrayList<String>();
   child = list;
   //onCreate(new Bundle()); 
   lv_child = (ListView)findViewById(R.id.lv_child); 
   String arr[]=child.toArray(new String[list.size()]);
   String[] Temp= new String[2];
          Temp[0] = arr[2].toString();
          array.add(Temp[0].split(":")[1]);
          String s = Temp[0].toString();
   ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,array);
   lv_child.setAdapter(adapter);
   //here you can work with your list
}

但我得到例外android.view.viewrootimpl$calledfromwrongthreadexception

请建议我,等待回复。

由于

2 个答案:

答案 0 :(得分:0)

尝试使用AsyncTask代替Thread来从服务器获取数据:

   public void fetchJSONChild(final GetChildList callBack){

        new AsyncTask<Void,Void,List<String>>(){
            @Override
            protected List<String> doInBackground(Void... params) {
                List<String> child = new ArrayList<String>();
                try {
                    URL url = new URL("http://192.168.x.xx:xxxx/childform_list/0.0.0.0/8069/new_db/admin/123456");
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setReadTimeout(30000 /* milliseconds */);
                    conn.setConnectTimeout(50000 /* milliseconds */);
                    conn.setRequestMethod("GET");
                    //conn.setRequestProperty("User-Agent", "GYUserAgentAndroid");
                    conn.setRequestProperty("Content-Type", "application/json");
                    conn.setDoInput(true);
                    //conn.setUseCaches (false);
                    // Starts the query
                    if (Build.VERSION.SDK != null && Build.VERSION.SDK_INT > 13) {

                        conn.setRequestProperty("Connection", "close");
                    }
                    conn.connect();

                    System.out.println("Before url.openStream()");
                    InputStream stream = conn.getInputStream();//.openStream();
                    System.out.println("After url.openStream()");
                    String data = convertStreamToString(stream);
                    // for examole data = "1,2,3";

                    child.addAll(Arrays.asList(data.split(",")));
                    readAndParseJSON(data);
                    stream.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
                return child;
            }

            @Override
            protected void onPostExecute(List<String> child) {
                super.onPostExecute(child);
                callBack.onGetChildList(child);
            }
        }.execute();

    }

答案 1 :(得分:0)

问题是您尝试从新的 onGetChildList(List<String> list)调用Thread方法。你不能这样做,因为你需要在UI上完成的所有工作都必须从主线程(有时称为UI线程)执行。您可以阅读更多相关信息here 我建议您在此处创建新的AsyncTask,并将run方法中的所有代码移到doInBackground()方法的最后一行。最新的行需要在AsyncTask#onPostExecute方法中移动,因此整个结构如下所示:

    new AsyncTask<Void,Void,List<String>>(){
        @Override
        protected List<String> doInBackground(Void... params) {
            List<String> child = new ArrayList<String>();
            try {
                // code omitted for brevity
            }catch (Exception e){
                e.printStackTrace();
            }
            return child;
        }

        @Override
        protected void onPostExecute(List<String> child) {
            super.onPostExecute(child);
            callBack.onGetChildList(child);
        }
    }.execute();

它将起作用,因为doInBackground()方法在后台线程内执行,当此方法完成时,AsyncTask将其结果传递给正在UI线程上执行的onPostExecuteAsyncTask专门用于此类任务 - 在后台执行某些操作,然后使用结果更新UI。