Еще один вопрос о жизненном цикле простого приложения для Android - PullRequest
2 голосов
/ 03 июля 2010

У меня есть действие с полем поиска с флажком «рядом с текущим местоположением» и списком для отображения результатов.Сейчас я нахожусь в жизненном цикле действия, реализуя методы onSaveInstanceState и onRestoreInstanceState.Когда действие уничтожено, и я возвращаюсь к нему, представление списка с результатами исчезло, но текст в поле поиска и состояние флажка восстановлены, а я ничего не сохранил в onSaveInstanceState.Зачем?Что сохраняется "автоматически" и что мне нужно сохранить в onSaveInstanceState?

public class Atable extends Activity {
    private EditText mSearch;
    private static final int ACTIVITY_EDIT=0;
    private Button mSearchButton;
    private TextView mNoresults;
    private TextView mytext;
    private ListView lv;
    private CheckBox checkBox;
    private LocationManager locationManager;    


    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);
        final Criteria 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(" ","+");           

                HttpClient httpclient = new DefaultHttpClient();    

                // Prepare a request object
                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;                   
                    }
                }

                HttpGet httpget = new HttpGet(url); 

                // 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();
                        final RestaurantList restaurantList = gson.fromJson(r, RestaurantList.class);

                        int nResults = restaurantList.getSize();

                        if (nResults>0) {

                            lv.setVisibility(View.VISIBLE);

                            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) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });

    }

    //Start a location listener
    LocationListener onLocationChange=new LocationListener() {
        public void onLocationChanged(Location loc) {
            //sets and displays the lat/long when a location is provided
            /*String latlong = "Lat: " + loc.getLatitude() + " Long: " + loc.getLongitude();   
            mytext.setText(latlong);*/
        }

        public void onProviderDisabled(String provider) {
        // required for interface, not used
        }

        public void onProviderEnabled(String provider) {
        // required for interface, not used
        }

        public void onStatusChanged(String provider, int status,
        Bundle extras) {
        // required for interface, not used
        }
    };

    //pauses listener while app is inactive
    @Override
    public void onPause() {
        super.onPause();
        locationManager.removeUpdates(onLocationChange);
    }

    //reactivates listener when app is resumed
    @Override
    public void onResume() {
        super.onResume();
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0,onLocationChange);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Toast.makeText(this, "Activity is getting killed", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {      
        Toast.makeText(this, "onRestoreInstanceState", Toast.LENGTH_LONG).show();
        super.onRestoreInstanceState(savedInstanceState);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {       
        Toast.makeText(this, "onSaveInstanceState", Toast.LENGTH_LONG).show();
        super.onSaveInstanceState(outState);
    }

}

1 Ответ

2 голосов
/ 03 июля 2010

Во-первых, не выполняйте сетевые запросы в потоке пользовательского интерфейса. Вы сделаете свой пользовательский интерфейс невосприимчивым к продолжительности операции и риску запуска ANRs . Попробуйте использовать AsyncTask для запроса вашего сервера.

По умолчанию Действия сохраняют и восстанавливают свое состояние иерархии представлений. Каждая реализация View отвечает за принятие решения о том, какие части его состояния следует сохранить и восстановить. ListView - это особый случай, как обычно.

ListView сохраняет состояние о текущей позиции списка и выборе элемента, но все это бесполезно без адаптера. Если вы установите адаптер до восстановления сохраненного состояния иерархии представлений в Activity#onRestoreInstanceState, ListView попытается повторно синхронизировать его состояние представления с данными.

Когда вызывается onSaveInstanceState и у вас есть данные о результатах, вы можете записать сохраненные результаты поиска в заданный вами Bundle.

В onCreate проверьте, не является ли указанный Bundle не null и присутствуют ли в нем ваши данные из предыдущего запроса. Если это так, прочитайте его обратно. Используйте его для создания нового адаптера и наберите setAdapter на вашем ListView. ListView должен взять его оттуда.

...