简体   繁体   English

无法在 AsyncTask 中未调用 Looper.prepare() 的线程内创建处理程序

[英]Can't create handler inside thread that has not called Looper.prepare() in AsyncTask

im trying to get the city using Geocoder that android have its app we creating as homework.我正在尝试使用 Geocoder 获取城市,Android 将其应用程序创建为家庭作业。 I'm trying to do it inside a AsyncTask but i get the this exception:我正在尝试在 AsyncTask 中执行此操作,但出现此异常:

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

the AsyncTask code:异步任务代码:

public class GeocoderTask extends AsyncTask<Void, Void, String> {

LocationManager locationManager;
Location location;
Context context;
String city;

public GeocoderTask(Context context) {
    this.context = context;
    locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
}

@SuppressLint("MissingPermission")
@Override
protected String doInBackground(Void... voids) {
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            GeocoderTask.this.location = location;
            Geocoder geocoder = new Geocoder(context, Locale.getDefault());
            List<Address> addresses;
            try {
               addresses  = geocoder.getFromLocation(GeocoderTask.this.location.getLatitude(), GeocoderTask.this.location.getLongitude(), 3);
               city = addresses.get(0).getLocality();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e){
                e.getMessage();
            }
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {

        }

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onProviderDisabled(String provider) {

        }
    });
    return city;
}

@Override
protected void onPostExecute(String s) {
    super.onPostExecute(s);
    FrgPersonInfo frgPersonInfo = new FrgPersonInfo();
    System.out.println(s);
    frgPersonInfo.saveUserToTable(s);
}

} }

I'm calling the AsyncTask from fragment the calling from the fragment:我正在从片段调用 AsyncTask 从片段调用:

 view.findViewById(R.id.btnRegister).setOnClickListener(new View.OnClickListener() {
        @SuppressLint("MissingPermission")
        @Override
        public void onClick(View v) {
            checkPermissions();
            GeocoderTask geocoderTask = new GeocoderTask(context);
            geocoderTask.execute();
        }
    });

the method I'm calling in onPostExecute in the AsyncTask:我在 AsyncTask 中的 onPostExecute 中调用的方法:

public void saveUserToTable(String city) {
    String age = uAge.getText().toString();
    String name = fName.getText().toString();

    UserInfo userInfo = new UserInfo();
    userInfo.setIsConnected(true);
    userInfo.setUserImage(imageUrl);
    userInfo.setAge(Integer.valueOf(age));
    userInfo.setName(name);
    userInfo.setCity(city);

    Backendless.Data.of(UserInfo.class).save(userInfo, new AsyncCallback<UserInfo>() {
        @Override
        public void handleResponse(UserInfo response) {
            System.out.println("Bitch, im here again!");
            ((TextView)parentView.findViewById(R.id.loginFrgBtn)).setTextColor(Color.BLUE);
            ((TextView)parentView.findViewById(R.id.registerFrgBtn)).setTextColor(Color.BLACK);

            FragmentTransaction ft = fm.beginTransaction();
            ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
            FrgLogin frgLogin = new FrgLogin();
            ft.replace(R.id.container, frgLogin);
            ft.commit();
            TastyToast.makeText(context, "Welcome!", TastyToast.LENGTH_LONG, TastyToast.SUCCESS).show();
        }

        @Override
        public void handleFault(BackendlessFault fault) {
            TastyToast.makeText(context, fault.getMessage(), TastyToast.LENGTH_LONG, TastyToast.ERROR).show();
        }
    });
}

the checkPermission:检查权限:

 private void checkPermissions() {
    List<String> neededPerms = new ArrayList<>();
    int fineGpsPerm = context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION);
    int coarseGpsPerm = context.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION);

    if (fineGpsPerm != PackageManager.PERMISSION_GRANTED || coarseGpsPerm != PackageManager.PERMISSION_GRANTED) {
        neededPerms.add(Manifest.permission.ACCESS_FINE_LOCATION);
        neededPerms.add(Manifest.permission.ACCESS_COARSE_LOCATION);
    }

    if (!neededPerms.isEmpty()) {
        ActivityCompat.requestPermissions( getActivity(), neededPerms.toArray(new String[neededPerms.size()]), GPS_PERM_CODE);
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode){
        case GPS_PERM_CODE:
            if (grantResults[0] != PackageManager.PERMISSION_GRANTED|| grantResults[1] != PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(context, "Need to Allow perms First", Toast.LENGTH_SHORT).show();
                checkPermissions();
            }
            break;
    }
}

the fragment class:片段类:

public class FrgPersonInfo extends Fragment{
public static final int GPS_PERM_CODE = 103;
Context context;
EditText fName, uAge, uCity;
String imageUrl = "";

FragmentManager fm;
View parentView;

LocationManager locationManager;
Location location;
boolean isLocEnabled = false;
String cityAddress = "";


@Override
public void onAttach(@NonNull Context context) {
    super.onAttach(context);
    this.context = context;
    System.out.println("in person onattach");
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@SuppressLint("MissingPermission")
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    //inflating the wanted fragmentView
    View myView = inflater.inflate(R.layout.frg_person_info, container, false);
    // init the fields
    fName = myView.findViewById(R.id.fName);
    uAge = myView.findViewById(R.id.userAge);
    uCity = myView.findViewById(R.id.userCity);
    fm = getActivity().getSupportFragmentManager();
    locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
    return myView;
}

@SuppressLint("MissingPermission")
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    parentView = view.getRootView();
    //creating a bundle so we can (in this case) get data
    Bundle bundle = getArguments();
    //use the get.. method to get data by key
//        imageUrl = bundle.getString(FrgRegister.IMAGE_KEY);
    checkPermissions();

    if (isLocEnabled) {

    } else {
        Toast.makeText(context, "dont have perms", Toast.LENGTH_SHORT).show();
    }


    view.findViewById(R.id.btnRegister).setOnClickListener(new View.OnClickListener() {
        @SuppressLint("MissingPermission")
        @Override
        public void onClick(View v) {
            checkPermissions();
            GeocoderTask geocoderTask = new GeocoderTask(context);
            geocoderTask.getUpdate();
        }
    });
}


@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
}

@Override
public void onDetach() {
    super.onDetach();
    this.fName = null;
    this.uAge = null;
    this.uCity = null;
    this.fm = null;
    this.imageUrl = null;
}


public void saveUserToTable(String city) {
    String age = uAge.getText().toString();
    String name = fName.getText().toString();

    UserInfo userInfo = new UserInfo();
    userInfo.setIsConnected(true);
    userInfo.setUserImage(imageUrl);
    userInfo.setAge(Integer.valueOf(age));
    userInfo.setName(name);
    userInfo.setCity(city);

    Backendless.Data.of(UserInfo.class).save(userInfo, new AsyncCallback<UserInfo>() {
        @Override
        public void handleResponse(UserInfo response) {
            System.out.println("Bitch, im here again!");
            ((TextView)parentView.findViewById(R.id.loginFrgBtn)).setTextColor(Color.BLUE);
            ((TextView)parentView.findViewById(R.id.registerFrgBtn)).setTextColor(Color.BLACK);

            FragmentTransaction ft = fm.beginTransaction();
            ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
            FrgLogin frgLogin = new FrgLogin();
            ft.replace(R.id.container, frgLogin);
            ft.commit();
            TastyToast.makeText(context, "Welcome!", TastyToast.LENGTH_LONG, TastyToast.SUCCESS).show();
        }

        @Override
        public void handleFault(BackendlessFault fault) {
            TastyToast.makeText(context, fault.getMessage(), TastyToast.LENGTH_LONG, TastyToast.ERROR).show();
        }
    });
}


private void checkPermissions() {
    List<String> neededPerms = new ArrayList<>();
    int fineGpsPerm = context.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION);
    int coarseGpsPerm = context.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION);

    if (fineGpsPerm != PackageManager.PERMISSION_GRANTED || coarseGpsPerm != PackageManager.PERMISSION_GRANTED) {
        neededPerms.add(Manifest.permission.ACCESS_FINE_LOCATION);
        neededPerms.add(Manifest.permission.ACCESS_COARSE_LOCATION);
    }

    if (!neededPerms.isEmpty()) {
        ActivityCompat.requestPermissions( getActivity(), neededPerms.toArray(new String[neededPerms.size()]), GPS_PERM_CODE);
    } else {
        isLocEnabled = true;
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode){
        case GPS_PERM_CODE:
            if (grantResults[0] != PackageManager.PERMISSION_GRANTED || grantResults[1] != PackageManager.PERMISSION_GRANTED) {
                checkPermissions();
            } else {
                isLocEnabled = true;
            }
            break;
    }
}
}

Asynctask is a Thread, which only executes the tasks which it should and doesn't need a Looper and though there is no Looper called for this Thread. Asynctask 是一个线程,它只执行它应该和不需要 Looper 的任务,尽管没有为此线程调用 Looper。 The Locationlistener works different, than that, what you have tried. Locationlistener工作方式与您尝试过的不同。 OnLocationchanged get's called as long as you don't stop the listener, but this is happening asynchronously and you can't just wait inside an asynctask for this to finish.只要您不停止侦听器,就会调用OnLocationchanged get,但这是异步发生的,您不能只是在asynctask等待它完成。 You have to start the locationlistener from your Mainthread and whenever your Location gets changed the function onLocationChanged gets called.您必须从onLocationChanged启动locationlistener onLocationChanged并且每当您的位置发生更改时,都会调用onLocationChanged函数。 You could for example put your onPostExecution inside the locationlistener.例如,您可以将 onPostExecution 放在位置侦听器中。

@Override
    public void onLocationChanged(Location location) {
        GeocoderTask.this.location = location;
        Geocoder geocoder = new Geocoder(context, Locale.getDefault());
        List<Address> addresses;
        try {
           addresses  = geocoder.getFromLocation(GeocoderTask.this.location.getLatitude(), GeocoderTask.this.location.getLongitude(), 3);
           city = addresses.get(0).getLocality();
           FrgPersonInfo frgPersonInfo = new FrgPersonInfo();
           System.out.println(city);
           frgPersonInfo.saveUserToTable(s);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e){
            e.getMessage();
        }
    }

Create the locationListener to keep a reference to it.创建 locationListener 以保留对它的引用。

Create a class to trigger the LocationUpdates创建一个类来触发 LocationUpdates

public class GeocoderTask {

LocationManager locationManager;
Location location;
Context context;
String city;

LocationListener locationListener = new LocationListener(){
@Override
    public void onLocationChanged(Location location) {
        GeocoderTask.this.location = location;
        Geocoder geocoder = new Geocoder(context, Locale.getDefault());
        List<Address> addresses;
        FrgPersonInfo frgPersonInfo = new FrgPersonInfo();
        System.out.println(city);
        frgPersonInfo.saveUserToTable(s);
        try {
           addresses  = geocoder.getFromLocation(GeocoderTask.this.location.getLatitude(), GeocoderTask.this.location.getLongitude(), 3);
           city = addresses.get(0).getLocality();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e){
            e.getMessage();
        }
    }
    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {}
    @Override
    public void onProviderEnabled(String provider) {}
    @Override
    public void onProviderDisabled(String provider) {}
}
public GeocoderTask(Context context) {
this.context = context;
locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
}

public void getUpdate(){
locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER,locationListener,null
}

You just have to create the class and use the locationListener to call the Function getUpdate, this will call the Update once.您只需要创建类并使用 locationListener 调用函数 getUpdate,这将调用一次 Update。 You could also use requestUpdates and create a function to remove the listener if you want more updates.如果需要更多更新,您还可以使用 requestUpdates 并创建一个函数来删除侦听器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无法在未在AsyncTask for ProgressDialog中调用Looper.prepare()的线程内创建处理程序 - Can't create handler inside thread that has not called Looper.prepare() inside AsyncTask for ProgressDialog Android 2.3无法在未调用Looper.prepare()(AsyncTask)的线程内创建处理程序 - Android 2.3 Can't create handler inside thread that has not called Looper.prepare() (AsyncTask) Android线程错误-无法在未调用Looper.prepare()的线程内创建处理程序 - Android thread error - Can't create handler inside thread that has not called Looper.prepare() 无法在警告对话框线程中未调用Looper.prepare()的线程内创建处理程序 - Can't create handler inside thread that has not called Looper.prepare() on alert dialog thread java.lang.RuntimeException:无法在尚未调用Looper.prepare()的线程内创建处理程序 - java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() java.lang.RuntimeException:无法在尚未调用 Looper.prepare() 的线程内创建处理程序错误 - java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() Error 无法在未调用Looper.prepare()Android的线程内创建处理程序 - Can't create handler inside thread that has not called Looper.prepare() Android java.lang.RuntimeException:无法在未在Android中调用Looper.prepare()的线程内创建处理程序 - java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() in Android RxJava无法在未调用Looper.prepare()的线程内创建处理程序 - RxJava Can't create handler inside thread that has not called Looper.prepare() 线程化-无法在未调用Looper.prepare()的线程内创建处理程序 - Threading - Can't create handler inside thread that has not called Looper.prepare()
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM