ViewRoot $ CalledFromWrongThreadException при попытке сделать спиннер видимым - PullRequest
0 голосов
/ 17 октября 2011

Я анализирую plist с сервера и на основании условия, что у меня есть счетчик для отображения и выбора значения из него.

Это мой код, который реализует это

public class RaconTours extends Activity implements OnClickListener {

@Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btn = (ImageButton) findViewById(R.id.arrowBtn);
        btn.setOnClickListener(this);
        tourArray = new ArrayList<Tour>();
        btnProfile = (ImageButton) findViewById(R.id.profileBtn);
        spinner = (Spinner) findViewById(R.id.spinner);

        checkSDcardSupport();
        dialog = ProgressDialog.show(RaconTours.this, "", "Loading...",
                true, true);
        splashThread = new Thread() {
            @Override
            public void run() {
                try {
                    /**** Specify the path of the plist file ****/
                    File f = new File(RaconTours.PATH
                            + Constants.TOUR_MASTER_PLIST);
                    if (!f.exists()) {
                        f.createNewFile();
                    }
                    if (f.length() <= 0) {
                        URL plistUrl = new URL(Constants.TOUR_PLIST_URL);
                        TourDescription.httpDownload(f, plistUrl);
                    }
                } catch (MalformedURLException mue) {
                    mue.printStackTrace();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
                /**** Call the method to parse the downloaded plist file ****/
                parsePlist();
                if(dialog!=null){
                    dialog.dismiss();
                }
            }
        };
        splashThread.start();



    }

Теперь внутри метода parsePlist,

    public void parsePlist() {


            try {
                /**** Opens and reads the downloaded file ****/

                InputStream is = new BufferedInputStream(new FileInputStream(
                        RaconTours.PATH + Constants.TOUR_MASTER_PLIST));
                XMLPropertyListConfiguration plist = new XMLPropertyListConfiguration(
                        is);

                HashMap<String, Object> dict = plist.mPlistHashMap;
                // check if more than 1 city exists, if they exist display a spinner to select the city
                if (dict.size() > 2) {
                    try {
                    spinner.setVisibility(View.VISIBLE);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    //dict.remove("venueicons");
                    for (Object objSpinner: dict.keySet()) {
                        spin =  (String) objSpinner.toString();
                        // add the keys to the string array list
                        spinnerKeys.add(spin);
                    }
                    // set the array list as the data for the adapter
                    ArrayAdapter<String> spinnerData=new ArrayAdapter<String>(this,
                            android.R.layout.simple_spinner_item,
                            spinnerKeys);

                    spinnerData.setDropDownViewResource(
                            android.R.layout.simple_spinner_dropdown_item);
                        spinner.setAdapter(spinnerData);

                    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                        public void onItemSelected(AdapterView<?> parent,
                                View view, int pos, long id) {
                            Object item = parent.getItemAtPosition(pos);
                            city = item.toString();
                        }

                        public void onNothingSelected(AdapterView<?> parent) {
                            Toast.makeText(getApplicationContext(), "Please select a city", Toast.LENGTH_SHORT).show();
                        }
                    });

                }
                for (Object key : dict.keySet()) {

                    if (key.toString().equals("venueicons")) {
                        continue;
                    }
                    city = key.toString();

                    HashMap<String, Object> cityDict = (HashMap<String, Object>) dict
                            .get(city);
                    for (Object cityKey : cityDict.keySet()) {

                         tour = new Tour();
    .....
            }
    }
catch (FileNotFoundException fnfe) {
    fnfe.printStackTrace();
}

Здесь я проверяю, что размер dict больше 2, то есть

if (dict.size ()> 2) {...

}

Исходя из этого, я делаю счетчик видимым, но он дает мне

10-17 08:24:33.240: WARN/System.err(4538): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
10-17 08:24:33.250: WARN/System.err(4538):     at android.view.ViewRoot.checkThread(ViewRoot.java:2932)
10-17 08:24:33.250: WARN/System.err(4538):     at android.view.ViewRoot.focusableViewAvailable(ViewRoot.java:1712)
10-17 08:24:33.260: WARN/System.err(4538):     at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:452)
10-17 08:24:33.270: WARN/System.err(4538):     at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:452)
10-17 08:24:33.270: WARN/System.err(4538):     at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:452)
10-17 08:24:33.290: WARN/System.err(4538):     at android.view.View.setFlags(View.java:4633)
10-17 08:24:33.290: WARN/System.err(4538):     at android.view.View.setVisibility(View.java:3116)
10-17 08:24:33.290: WARN/System.err(4538):     at com.racontrs.Racontours.RaconTours.parsePlist(RaconTours.java:157)
10-17 08:24:33.300: WARN/System.err(4538):     at com.racontrs.Racontours.RaconTours$1.run(RaconTours.java:85)

для линии

spinner.setVisibility (Просмотреть.VISIBLE);

Любой ответ на этот вопрос?

Ответы [ 2 ]

0 голосов
/ 17 октября 2011

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

0 голосов
/ 17 октября 2011

Ваш splashThread работает в своем собственном потоке (не в потоке пользовательского интерфейса), это означает, что вызов parseList также будет выполняться в потоке, не являющемся пользовательским интерфейсом, что приводит к тому, что изменения в пользовательском интерфейсе становятся «недопустимым» действием.

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

AsyncTask-пример

Замените ваш метод parsePList() следующим:

private class PListParser extends AsyncTask<Void, Void, Boolean> {
  public Boolean doInBackground( Void... params ) {
    //do the things your method parsePList does here.

    if( dict.size() > 2 )
      return true;
    else
      return false;
  }

  public void onPostExecute( Boolean result ) {
    //result is the return-value of the doInBackground-method
    if( result )
      spinner.setVisibility( View.VISIBLE );
    else
      spinner.setVisibility( View.GONE );
  }
}

Тогда вместо того, чтобы звонить parsePList(), вы делаете это: new PListParser().execute()

...