1

Web サービスから取得したデータに ListView を設定したいと思います。AsyncTask インスタンスでデータを取得しますが、ListView 属性の一部を設定しようとするとクラッシュします ("lv.setVisibility(View.VISIBLE);" 行で)。誰でも助けることができますか?

ありがとう

public class Atable extends Activity {

    private EditText mSearch;
    private static final int ACTIVITY_EDIT=0;
    private Button mSearchButton;
    private TextView mNoresults;
    private ListView lv;
    private CheckBox checkBox;
    private LocationManager locationManager;
    private RestaurantList restaurantList;
    private Criteria criteria;

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        lv= (ListView)findViewById(R.id.listview);

        mNoresults = (TextView) findViewById(R.id.noresults);  
        mNoresults.setVisibility(View.GONE);

        mSearchButton = (Button)this.findViewById(R.id.button);
        checkBox = (CheckBox) findViewById(R.id.local_check);        

        locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
        criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_FINE);

        mSearchButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mNoresults.setVisibility(View.GONE);
                mSearch = (EditText) findViewById(R.id.search);  
                String tmp_str = mSearch.getText().toString().replace(" ","+");  
                String url = "http://www.atable.org/getRestaurantByQuery/?query=" + tmp_str;

                if (checkBox.isChecked()) {

                    //get location
                    String provider = locationManager.getBestProvider(criteria, true);                
                    Location location = locationManager.getLastKnownLocation(provider);

                    if (location!=null) {

                        String lat = String.valueOf(location.getLatitude());
                        String lng = String.valueOf(location.getLongitude());

                        url += "&lat="+lat+"&lng="+lng;                   
                    }
                }
                new GetRestaurantData().execute(url);               
            }
        });

    };

    private class GetRestaurantData extends AsyncTask<String, Boolean, RestaurantList> {

        private HttpClient httpclient = new DefaultHttpClient();

        @Override
        protected RestaurantList doInBackground(String... url) {            

            publishProgress(true);         

            HttpGet httpget = new HttpGet(url[0]);          

            // Execute the request
            HttpResponse response;
            try {
                response = httpclient.execute(httpget);
                HttpEntity entity = response.getEntity();

                if (entity != null) {

                    InputStream instream = entity.getContent();

                    Reader r = new InputStreamReader(instream);                      

                    Gson gson = new Gson();
                    restaurantList = gson.fromJson(r, RestaurantList.class);

                    int nResults = restaurantList.getSize();

                    if (nResults>0) {                       

                        lv.setVisibility(View.VISIBLE); //app crashes here                      

                        lv.setAdapter( new ArrayAdapter<String>(Atable.this ,android.R.layout.simple_list_item_1,restaurantList.getRestaurantNames()));

                        lv.setOnItemClickListener(new OnItemClickListener() {

                            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                                Intent intent = new Intent(Atable.this, RestaurantDescription.class);
                                Restaurant tmp_resto = restaurantList.getRestaurant((int)id);

                                String tmp_categories = tmp_resto.getCategories().get(0);
                                for (int i=1; i<tmp_resto.getCategories().size(); i++) {
                                    tmp_categories+=", "+tmp_resto.getCategories().get(i);
                                }

                                String address = tmp_resto.getStreet()+", "+tmp_resto.getStreetNumber()+"\n"+tmp_resto.getCity()+
                                                " "+tmp_resto.getPostalCode()+"\n"+tmp_resto.getCountry();

                                intent.putExtra("name", tmp_resto.getName());
                                intent.putExtra("address", address);                                
                                intent.putExtra("rating", tmp_resto.getRating());
                                intent.putExtra("price_range", tmp_resto.getPriceRange());
                                intent.putExtra("categories", tmp_categories);
                                intent.putExtra("latitude", tmp_resto.getLatitude());
                                intent.putExtra("longitude", tmp_resto.getLongitude());
                                startActivityForResult(intent, ACTIVITY_EDIT);
                            }
                        });


                    }

                    else {
                        lv.setVisibility(View.GONE);
                        mNoresults.setVisibility(View.VISIBLE);
                    }

                    //Closing the input stream will trigger connection release
                    instream.close();
                }   


            } catch (ClientProtocolException e) {                   
                e.printStackTrace();
            } catch (IOException e) {                   
                e.printStackTrace();
            }

            return restaurantList;
        }

        @Override
        protected void onProgressUpdate(Boolean... progress) {
            // line below coupled with 
            //    getWindow().requestFeature(Window.FEATURE_INDETERMINATE_PROGRESS) 
            //    before setContentView 
            // will show the wait animation on the top-right corner
            Atable.this.setProgressBarIndeterminateVisibility(progress[0]);
        }

        @Override
        protected void onPostExecute(RestaurantList result) {
            publishProgress(false);
            // Do something with result in your activity
        }




    }
4

2 に答える 2

1

Androidでは、すべてのUI更新はメインスレッド(UIスレッドとも呼ばれます)で行われます。UIをブロックしないようにするために、時間のかかるタスクを実行するために新しいスレッドを生成する場合に適しています。

ただし、あらゆる種類の不確定な動作を回避するには、UIの更新を常にUIスレッドで実行する必要があります。別のスレッドからこれを行おうとすると、例外がスローされます。

ListViewあなたの例では、の値に基づいてさまざまな更新を実行していることがわかりますnResults。に戻っnResultsてみることができdoInBackground()ます。に渡されonPostExecute()、UIスレッドで実行されます。

Androidでのスレッド化に関するいくつかの有用な情報については、この記事をチェックしてください:http: //android-developers.blogspot.com/2009/05/painless-threading.html

HTH

于 2010-07-04T18:11:14.577 に答える
0

doinbachground メソッドから ui スレッドにアクセスすることはできません..実行後、実行前、または進行中の更新メソッドからアクセスする必要があります...

于 2010-07-04T17:19:06.060 に答える