【问题标题】:Trying to get location - Only the original thread that created a view hierarchy can touch its views.试图获取位置 - 只有创建视图层次结构的原始线程才能触及其视图。
【发布时间】:2014-07-01 01:22:43
【问题描述】:

我正在尝试从 gps 获取位置,但是,当我等待结果时,我从我的日志猫中获取了这个位置,并且列表视图保持为空。

LogCat:

07-01 03:19:52.747: E/AndroidRuntime(31839): FATAL EXCEPTION: Timer-0
07-01 03:19:52.747: E/AndroidRuntime(31839): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
07-01 03:19:52.747: E/AndroidRuntime(31839):    at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4056)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at android.view.ViewRootImpl.focusableViewAvailable(ViewRootImpl.java:2210)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:657)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:657)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:657)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:657)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:657)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:657)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:657)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at android.view.ViewGroup.focusableViewAvailable(ViewGroup.java:657)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at android.view.View.setFlags(View.java:6736)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at android.view.View.setFocusableInTouchMode(View.java:4714)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at android.widget.AdapterView.checkFocus(AdapterView.java:705)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at android.widget.ListView.setAdapter(ListView.java:461)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at com.myapp.Main.initList(Main.java:677)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at com.myapp.Main.access$5(Main.java:670)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at com.myapp.Main$4.gotLocation(Main.java:344)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at com.myapp.services.MyLocation$GetLastLocation.run(MyLocation.java:119)
07-01 03:19:52.747: E/AndroidRuntime(31839):    at java.util.Timer$TimerImpl.run(Timer.java:284)

这是我的方法:

LocationManager locationManager = (LocationManager) a
                .getSystemService(Context.LOCATION_SERVICE);

        Criteria locationCritera = new Criteria();
        locationCritera.setAccuracy(Criteria.ACCURACY_COARSE);
        locationCritera.setAltitudeRequired(false);
        locationCritera.setBearingRequired(false);
        locationCritera.setCostAllowed(true);
        locationCritera.setPowerRequirement(Criteria.NO_REQUIREMENT);

        String providerName = locationManager.getBestProvider(locationCritera,
                true);

        if (providerName != null
                && locationManager.isProviderEnabled(providerName)) {

            LocationResult locationResult = new LocationResult() {

                @Override
                public void gotLocation(Location location) {
                    if (location == null) {
                        Log.v("--", "YEST");
                    }
                    // Got the location!
                    Geocoder gcd = new Geocoder(a, Locale.getDefault());
                    List<Address> addresses;
                    try {
                        Log.v("--",
                                location.getLatitude() + " | "
                                        + location.getLongitude());
                        addresses = gcd.getFromLocation(location.getLatitude(),
                                location.getLongitude(), 1);

                        if (addresses.isEmpty())
                            // if (addresses.size() > 0)
                            // System.out.println(addresses.get(0).getLocality());
                            // city = addresses.get(0).getLocality();
                            country = addresses.get(0).getCountryName();

                    } catch (IOException e) {

                        city = a.getString(R.string.app_name);
                        country = "";

                        // notf

                        Log.v("--", prefs.getBoolean("athan", false) + " tr1");

                        // notf end

                        e.printStackTrace();
                    }

                    prefs.edit().putString(Constants.COUNTRY, country).commit();
                    prefs.edit().putString(Constants.CITY, city).commit();
                    stringLatitude = String.valueOf(location.getLatitude());
                    stringLongitude = String.valueOf(location.getLongitude());
                    prefs.edit()
                            .putString(Constants.LONGITUDE, stringLongitude)
                            .commit();
                    prefs.edit().putString(Constants.LATITUDE, stringLatitude)
                            .commit();
                    AthanTime calcTimes = TestCalculation(location);

                    times = new ArrayList<TimeObjects>();

                    Calendar c = Calendar.getInstance();

                    SimpleDateFormat df = new SimpleDateFormat(
                            "EEE, d MMM yyyy");
                    String formattedDate = df.format(c.getTime());
                    try {
                        title.setText(city + "\n" + formattedDate);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    times.add(new TimeObjects(calcTimes.getFajr().toString(),
                            "Fajr", R.drawable.pray_fajr, a
                                    .getString(R.string.ar_fajr), prefs
                                    .getBoolean("item" + 0, true)));
                    times.add(new TimeObjects(
                            calcTimes.getSunrise().toString(), "Shorrok",
                            R.drawable.pray_maghreb, a
                                    .getString(R.string.ar_shorok), prefs
                                    .getBoolean("item" + 1, false)));
                    times.add(new TimeObjects(calcTimes.getDhuhr().toString(),
                            "Dhuhr", R.drawable.pray_dhurh, a
                                    .getString(R.string.ar_dhuhr), prefs
                                    .getBoolean("item" + 2, true)));
                    times.add(new TimeObjects(calcTimes.getAsr().toString(),
                            "Asr", R.drawable.pray_asr, a
                                    .getString(R.string.ar_asr), prefs
                                    .getBoolean("item" + 3, true)));

                    times.add(new TimeObjects(
                            calcTimes.getMaghrib().toString(), "Maghrib",
                            R.drawable.pray_maghreb, a
                                    .getString(R.string.ar_magrib), prefs
                                    .getBoolean("item" + 4, true)));
                    times.add(new TimeObjects(calcTimes.getIsha().toString(),
                            "Isha", R.drawable.pray_maghreb, a
                                    .getString(R.string.ar_isha), prefs
                                    .getBoolean("item" + 5, true)));
                    double diff = 25;
                    int difPos = 0;
                    for (int i = 0; i < times.size(); i++) {
                        if (times.get(i).isInNotification())
                            setRepeatingAlarm(
                                    times.get(i).getTime(),
                                    i,
                                    times.get(i).getTitle()
                                            + a.getString(R.string._at_)
                                            + times.get(i).getTime()
                                            + a.getString(R.string._in_) + city);
                        if (getTimeDifference(times.get(i).getTime()) > 0)
                            if (getTimeDifference(times.get(i).getTime()) < diff) {
                                diff = getTimeDifference(times.get(i).getTime());
                                difPos = i;
                            }
                    }
                    nextPrayTime = times.get(difPos);

                    initList();
                    listenToScroll();
                    intImages();

                    titleView = a.findViewById(R.id.main_actionbar_layout);
                }
            };
            MyLocation myLocation = new MyLocation();
            myLocation.getLocation(a, locationResult);

这里是 MyLocation.class:

public class MyLocation {
    Timer timer1;
    LocationManager lm;
    LocationResult locationResult;
    boolean gps_enabled = false;
    boolean network_enabled = false;
    private Context context;

    public boolean getLocation(Context context, LocationResult result) {
        // I use LocationResult callback class to pass location value from
        // MyLocation to user code.
        locationResult = result;
        this.context = context;
        if (lm == null)
            lm = (LocationManager) context
                    .getSystemService(Context.LOCATION_SERVICE);

        // exceptions will be thrown if provider is not permitted.
        try {
            gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
        } catch (Exception ex) {
        }
        try {
            network_enabled = lm
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        } catch (Exception ex) {
        }

        // don't start listeners if no provider is enabled
        if (!gps_enabled && !network_enabled)
            return false;

        if (gps_enabled)
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
                    locationListenerGps);
        if (network_enabled)
            lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0,
                    locationListenerNetwork);
        timer1 = new Timer();
        timer1.schedule(new GetLastLocation(), 20000);
        return true;
    }

    LocationListener locationListenerGps = new LocationListener() {
        public void onLocationChanged(Location location) {
            timer1.cancel();
            locationResult.gotLocation(location);
            lm.removeUpdates(this);
            lm.removeUpdates(locationListenerNetwork);
        }

        public void onProviderDisabled(String provider) {
        }

        public void onProviderEnabled(String provider) {
        }

        public void onStatusChanged(String provider, int status, Bundle extras) {
        }
    };

    LocationListener locationListenerNetwork = new LocationListener() {
        public void onLocationChanged(Location location) {
            timer1.cancel();
            locationResult.gotLocation(location);
            lm.removeUpdates(this);
            lm.removeUpdates(locationListenerGps);
        }

        public void onProviderDisabled(String provider) {
        }

        public void onProviderEnabled(String provider) {
        }

        public void onStatusChanged(String provider, int status, Bundle extras) {
        }
    };

    class GetLastLocation extends TimerTask {
        @Override
        public void run() {
            lm.removeUpdates(locationListenerGps);
            lm.removeUpdates(locationListenerNetwork);

            Location net_loc = null, gps_loc = null;
            if (gps_enabled)
                gps_loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            if (network_enabled)
                net_loc = lm
                        .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

            // if there are both values use the latest one
            if (gps_loc != null && net_loc != null) {
                if (gps_loc.getTime() > net_loc.getTime())
                    locationResult.gotLocation(gps_loc);
                else
                    locationResult.gotLocation(net_loc);
                return;
            }

            if (gps_loc != null) {
                locationResult.gotLocation(gps_loc);
                return;
            }
            if (net_loc != null) {
                locationResult.gotLocation(net_loc);
                return;
            }
            locationResult.gotLocation(null);
        }
    }

    public static abstract class LocationResult {

        public abstract void gotLocation(Location location);

    }
}

【问题讨论】:

    标签: android multithreading android-listview android-asynctask android-location


    【解决方案1】:

    正如异常消息所说:您不能从后台线程修改视图。

    获得 GPS 结果后,您必须在 ma​​in (UI) 线程上执行 initList()(以及任何其他更新 UI 的方法)。如果此代码在 Activity 中,则可以使用 runOnUiThread()。否则,您可以将HandlerAsyncTask 用于相同目的。

    【讨论】:

      【解决方案2】:

      那是因为您在 UI 线程之外调用 UI 代码。

      我不确定到底是什么线,但我认为它们是:

       initList();
       listenToScroll();
       intImages();
      

      如果您在活动中,请在 runOnUiThread 调用中调用它们:

      runOnUiThread(new Runnable()
      {
           @Override
           public void run()
           {
               initList();
               listenToScroll();
               intImages();
           }
      }
      

      如果您在另一个班级,则需要使用处理程序。 只需在您知道在 UI 线程上运行的某个位置创建处理程序

      mHandler = new Handler();
      

      然后使用带有可运行对象的“post”。

      mHandler.post(new Runnable()
      {
           @Override
           public void run()
           {
               initList();
               listenToScroll();
               intImages();
           }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-26
        • 1970-01-01
        • 2018-04-12
        • 2011-11-20
        • 2018-05-30
        • 2016-01-17
        相关资源
        最近更新 更多