Error: Can't create handler inside thread that has not called Looper.prepare()

穿精又带淫゛_ 提交于 2020-02-25 06:33:45

问题


Im getting that famous "Can't create handler inside thread that has not called Looper.prepare()" error in my below code. based on most of my Google search result, this happens when i try to update UI from my none-ui-thread, but im not updating the UI at this point when i call the method from my other helper class (only after address has been returned); so please consult on why this is happening would be appreciated.

package com.parspake.kookojapost;

import android.app.ActionBar;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.location.*;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class TextShare extends Activity {


    ConnectionHandler textPageConn;
    TextView dt2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.text_share);

        textPageConn = new ConnectionHandler(this);
        dt2 = (TextView) findViewById(R.id.show_location_text_page);

        Thread thread1 = new Thread(new Runnable() {

            @Override
            public void run() {

                textPageConn.getLocation();
                do {

                    if (textPageConn.mAddress != null) {
                        dt2.setText(textPageConn.mAddress);
                        break;
                    } else {
                        Log.d("debug","no location");
                    }

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                } while (textPageConn.mAddress == null);
            }

        });
        thread1.start();
    }
}

this is the exception that i get:

07-04 23:59:38.730: E/AndroidRuntime(7149): FATAL EXCEPTION: Thread-8482
07-04 23:59:38.730: E/AndroidRuntime(7149): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
07-04 23:59:38.730: E/AndroidRuntime(7149):     at android.os.Handler.<init>(Handler.java:121)
07-04 23:59:38.730: E/AndroidRuntime(7149):     at android.location.LocationManager$ListenerTransport$1.<init>(LocationManager.java:183)
07-04 23:59:38.730: E/AndroidRuntime(7149):     at android.location.LocationManager$ListenerTransport.<init>(LocationManager.java:183)
07-04 23:59:38.730: E/AndroidRuntime(7149):     at android.location.LocationManager._requestLocationUpdates(LocationManager.java:661)
07-04 23:59:38.730: E/AndroidRuntime(7149):     at android.location.LocationManager.requestLocationUpdates(LocationManager.java:486)
07-04 23:59:38.730: E/AndroidRuntime(7149):     at com.parspake.kookojapost.ConnectionHandler.getLocation(ConnectionHandler.java:136)
07-04 23:59:38.730: E/AndroidRuntime(7149):     at com.parspake.kookojapost.TextShare$2.run(TextShare.java:69)
07-04 23:59:38.730: E/AndroidRuntime(7149):     at java.lang.Thread.run(Thread.java:856)

so ConnectionHandler.java:136 is -> mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 50, mlocationListener);

and TextShare.java:69 is -> textPageConn.getLocation();

this is my ConnectionHandler Helper class:

package com.parspake.kookojapost;

import android.content.Context;
import android.location.*;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import java.io.IOException;
import java.util.List;
import java.util.Locale;

public class ConnectionHandler {

    private Context ctx;
    double mLat;
    double mLong;
    String currCity;
    String currCountry;
    String mAddress;
    LocationManager mLocationManager;
    LocationListener mlocationListener;

    public ConnectionHandler(Context context) {
        this.ctx = context;
    }


    public boolean locationSourceEnabled() {
        mLocationManager = (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE);
        boolean isInternetLocationAvailable = mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        boolean isGpsAvailable = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        if (isInternetLocationAvailable) {
            return true;
        } else if (isGpsAvailable) {
            return true;
        }
        return false;
    }


    public void getLocation() {

        mlocationListener = new LocationListener() {
            @Override
            public void onLocationChanged(Location location) {

                mLat = location.getLatitude();
                mLong = location.getLongitude();

                Geocoder gcd = new Geocoder(ctx, Locale.getDefault());
                List<Address> addresses;
                try {
                    addresses = gcd.getFromLocation(mLat, mLong, 1);
                    if (addresses.size() > 0) {
                        currCity = addresses.get(0).getLocality();
                        currCountry =  addresses.get(0).getCountryName();
                        mAddress = currCity + " - " + currCountry;
                    }
                } catch (IOException e) {
                    Log.d("omid debug", e.getMessage());
                }
            }

            @Override
            public void onStatusChanged(String s, int i, Bundle bundle) {
            }

            @Override
            public void onProviderEnabled(String s) {
            }

            @Override
            public void onProviderDisabled(String s) {
            }
        };
        mLocationManager = (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE);
        if (locationSourceEnabled()) {
            if (mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
                mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 50, mlocationListener);
            }
            if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 50, mlocationListener);
            }
        }
    }
}

回答1:


Ok the problem is that requestLocationUpdates is an asynchronous call, meaning that you don't need to run it on another thread and also means if you try to you are effectively making a handler on another thread which is not allowed. So instead you can remove the thread and just run this all on onCreate() (since you are only doing async calls)

reference: requestLocationUpdates gives error "Can't create Handler inside thread that has not called Looper.prepare()

Instead you could put your syncronous calls in another thread...

@Override
public void onLocationChanged(Location location) {
     new Thread(new Runnable() {

        @Override
        public void run() {
             mLat = location.getLatitude();
             mLong = location.getLongitude();

             Geocoder gcd = new Geocoder(ctx, Locale.getDefault());
             List<Address> addresses;
             try {
                 addresses = gcd.getFromLocation(mLat, mLong, 1);
                 if (addresses.size() > 0) {
                     currCity = addresses.get(0).getLocality();
                     currCountry =  addresses.get(0).getCountryName();
                     mAddress = currCity + " - " + currCountry;
                 }
             } catch (IOException e) {
                 Log.d("omid debug", e.getMessage());
             }
        }
    }).start();
}



回答2:


You can't update TextView from non-UI thread.

Use runOnUiThread instead:

runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        dt2.setText(textPageConn.mAddress);
                    }
                });



回答3:


Its not possible to change the ui content in other thread.. you can solve these problem in basically 2 ways

  • Using runOnUiThread() method, its simple , but it is not best practice
  • Another way is by using handler with callback handler(Callback c), its recommended one

I'll suggest to use handler with callback method. You can get great tutorial here. handler with callback in thread



来源:https://stackoverflow.com/questions/17476847/error-cant-create-handler-inside-thread-that-has-not-called-looper-prepare

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!