Android: "AsyncTask" dan foydalanganda "Qidirish zarrachasi tayyorlangan Looper thread" bo'lishi kerak

GPS o'lchamini 20 metrli aniqlik bilan olish uchun AsyncTask yaratdim. Haqiqat aniqlanmaguncha, aylanish jarayonini bajarishni istayman.

Muammo shundaki, men bir pozitsiyani yangilashni talab qilganda istisno oldim.

java.lang.NullPointerException: Calling thread must be a prepared Looper thread.

Bu kod xato kodi

@Override
protected String doInBackground(Void... params) {
if (ActivityCompat.checkSelfPermission(activity, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(activity, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                return null;
            }
            mLocationRequest.setInterval(100);
            mLocationRequest.setPriority(100);
            mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
            while (mLastLocation == null || (mLastLocation.getAccuracy()>Float.parseFloat("20.0") && mLastLocation.hasAccuracy())){
                try {
                    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest,activity);
                    mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
                } catch (SecurityException secex) {

                }
            }

            return null;
        }
1
oldin doInBackgroud() Looper.perpare() ni qo'shing. Ishonchim komil emas, balki sinab ko'ring.
qo'shib qo'ydi muallif L. Swifter, manba
oldin doInBackgroud() Looper.perpare() ni qo'shing. Ishonchim komil emas, balki sinab ko'ring.
qo'shib qo'ydi muallif L. Swifter, manba
oldin doInBackgroud() Looper.perpare() ni qo'shing. Ishonchim komil emas, balki sinab ko'ring.
qo'shib qo'ydi muallif L. Swifter, manba
to'liq jurnali chiqqani yozing
qo'shib qo'ydi muallif arjun, manba
to'liq jurnali chiqqani yozing
qo'shib qo'ydi muallif arjun, manba
to'liq jurnali chiqqani yozing
qo'shib qo'ydi muallif arjun, manba
Sizda doInBackgroud() bilan bog'liq bo'lgan UI bilan ishlayapsiz
qo'shib qo'ydi muallif Nouman Ghaffar, manba
Sizda doInBackgroud() bilan bog'liq bo'lgan UI bilan ishlayapsiz
qo'shib qo'ydi muallif Nouman Ghaffar, manba

10 javoblar

Men bu bilan to'liq ish kuni bilan mashg'ul bo'ldim. Xizmatda fonda ishlaydigan FusedLocationApi mavjud.

Men nima qildim - men uni boshqa bir joyda o'qiyman - Looper.getMainLooper() ni requestLocationUpdates() ning oxirgi parametri sifatida qo'shish.

Shunday qilib, buning o'rniga

LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest,activity);

Sizda bo'ladi

LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this, Looper.getMainLooper());

Agar barcha FusedLocationProviderApi sahifasini o'qigan bo'lsangiz, usuli parametrlarga qarab turli xil ishlarni amalga oshiradi.

8
qo'shib qo'ydi
Ha, sizning yechimingiz mening foydalanishimga mos emas edi. Orqa fonda olib boriladigan usulda bir marta joy kerak bo'lib, GPSni saqlashni xohlamadim. Sizda mavjud bo'lgan joy, ehtimol, joylashuv uchun ko'proq ishlatiladigan hol.
qo'shib qo'ydi muallif Peter Green, manba
Mening yangi javobimni ko'ring. MainThread muammosidan qochish kerak. stackoverflow.com/a/45068298/42994
qo'shib qo'ydi muallif Peter Green, manba
Bu bilan ehtiyot bo'ling! Sizning qayta chaqiruvingizdagi barcha kodlar mainUI threadida ishlaydi. Yuqori kod bo'lsa, sizning arizangizni jirkanch qilishingiz mumkin.
qo'shib qo'ydi muallif Peter Green, manba
Men bu masalani hal qilish uchun turli uslublarni qo'lladim. Hatto o'z looper va ishlovchilarni ham qo'ydim, lekin ishlamadi. Joylashuv yangiliklarini olish uchun ushbu usuldan foydalanishni to'xtataman. Buni amalga oshirish uchun FusedLocationClient dan foydalanmoqdaman, u bu parametrni talab qilmaydi.
qo'shib qo'ydi muallif Pedro Varela, manba
Bu erda yangi javobni o'qing. stackoverflow.com/a/45149156/3997720
qo'shib qo'ydi muallif Pedro Varela, manba
Siz Guava dan foydalanmoqdasiz. Ayniqsa, Guava Google tomonidan ishlab chiqilgan bo'lsa ham, men asosga tayanaman.
qo'shib qo'ydi muallif Pedro Varela, manba

Men bu bilan to'liq ish kuni bilan mashg'ul bo'ldim. Xizmatda fonda ishlaydigan FusedLocationApi mavjud.

Men nima qildim - men uni boshqa bir joyda o'qiyman - Looper.getMainLooper() ni requestLocationUpdates() ning oxirgi parametri sifatida qo'shish.

Shunday qilib, buning o'rniga

LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest,activity);

Sizda bo'ladi

LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this, Looper.getMainLooper());

Agar barcha FusedLocationProviderApi sahifasini o'qigan bo'lsangiz, usuli parametrlarga qarab turli xil ishlarni amalga oshiradi.

8
qo'shib qo'ydi
Ha, sizning yechimingiz mening foydalanishimga mos emas edi. Orqa fonda olib boriladigan usulda bir marta joy kerak bo'lib, GPSni saqlashni xohlamadim. Sizda mavjud bo'lgan joy, ehtimol, joylashuv uchun ko'proq ishlatiladigan hol.
qo'shib qo'ydi muallif Peter Green, manba
Mening yangi javobimni ko'ring. MainThread muammosidan qochish kerak. stackoverflow.com/a/45068298/42994
qo'shib qo'ydi muallif Peter Green, manba
Bu bilan ehtiyot bo'ling! Sizning qayta chaqiruvingizdagi barcha kodlar mainUI threadida ishlaydi. Yuqori kod bo'lsa, sizning arizangizni jirkanch qilishingiz mumkin.
qo'shib qo'ydi muallif Peter Green, manba
Bu erda yangi javobni o'qing. stackoverflow.com/a/45149156/3997720
qo'shib qo'ydi muallif Pedro Varela, manba
Siz Guava dan foydalanmoqdasiz. Ayniqsa, Guava Google tomonidan ishlab chiqilgan bo'lsa ham, men asosga tayanaman.
qo'shib qo'ydi muallif Pedro Varela, manba
Men bu masalani hal qilish uchun turli uslublarni qo'lladim. Hatto o'z looper va ishlovchilarni ham qo'ydim, lekin ishlamadi. Joylashuv yangiliklarini olish uchun ushbu usuldan foydalanishni to'xtataman. Buni amalga oshirish uchun FusedLocationClient dan foydalanmoqdaman, u bu parametrni talab qilmaydi.
qo'shib qo'ydi muallif Pedro Varela, manba

Men bu bilan to'liq ish kuni bilan mashg'ul bo'ldim. Xizmatda fonda ishlaydigan FusedLocationApi mavjud.

Men nima qildim - men uni boshqa bir joyda o'qiyman - Looper.getMainLooper() ni requestLocationUpdates() ning oxirgi parametri sifatida qo'shish.

Shunday qilib, buning o'rniga

LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest,activity);

Sizda bo'ladi

LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this, Looper.getMainLooper());

Agar barcha FusedLocationProviderApi sahifasini o'qigan bo'lsangiz, usuli parametrlarga qarab turli xil ishlarni amalga oshiradi.

8
qo'shib qo'ydi
Ha, sizning yechimingiz mening foydalanishimga mos emas edi. Orqa fonda olib boriladigan usulda bir marta joy kerak bo'lib, GPSni saqlashni xohlamadim. Sizda mavjud bo'lgan joy, ehtimol, joylashuv uchun ko'proq ishlatiladigan hol.
qo'shib qo'ydi muallif Peter Green, manba
Mening yangi javobimni ko'ring. MainThread muammosidan qochish kerak. stackoverflow.com/a/45068298/42994
qo'shib qo'ydi muallif Peter Green, manba
Bu bilan ehtiyot bo'ling! Sizning qayta chaqiruvingizdagi barcha kodlar mainUI threadida ishlaydi. Yuqori kod bo'lsa, sizning arizangizni jirkanch qilishingiz mumkin.
qo'shib qo'ydi muallif Peter Green, manba
Siz Guava dan foydalanmoqdasiz. Ayniqsa, Guava Google tomonidan ishlab chiqilgan bo'lsa ham, men asosga tayanaman.
qo'shib qo'ydi muallif Pedro Varela, manba
Men bu masalani hal qilish uchun turli uslublarni qo'lladim. Hatto o'z looper va ishlovchilarni ham qo'ydim, lekin ishlamadi. Joylashuv yangiliklarini olish uchun ushbu usuldan foydalanishni to'xtataman. Buni amalga oshirish uchun FusedLocationClient dan foydalanmoqdaman, u bu parametrni talab qilmaydi.
qo'shib qo'ydi muallif Pedro Varela, manba
Bu erda yangi javobni o'qing. stackoverflow.com/a/45149156/3997720
qo'shib qo'ydi muallif Pedro Varela, manba

DoInBackground-da ishlayotganda foydalanuvchi interfeysida o'zgarishlar qilish yoki doInBackground tashqari usullarni o'zgartirish uchun Looper.prepare() yoki runOnUiThread() funksiyasidan foydalaning

Misol:

 runOnUiThread(new Runnable() {
            @Override
            public void run() {
                progressBar = new ProgressDialog(MainActivity.this);
                progressBar.setCancelable(false);
                progressBar.setTitle("Downloading Files...");
                progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                progressBar.setProgress(0);
                progressBar.setMax(100);
                progressBar.show();
            }
        });
2
qo'shib qo'ydi
Javobni tahrirladim.
qo'shib qo'ydi muallif Ashwin Mothilal, manba
Agar Looper.prepare() ishlayotgan bo'lsa, siz bir vaqtning o'zida bir nechta runnables ishlayapsiz. Iltimos, buni tekshirib ko'ring
qo'shib qo'ydi muallif Ashwin Mothilal, manba
Looper.prepare() ishlarga o'xshaydi! UIda o'zgarishlar qilmaganligim sababi nima uchun kerakligini tushunmayapman. (Google qidiruvi UI tarkibiga kiradimi?)
qo'shib qo'ydi muallif michael, manba
runOnUiThread() ishlatish uchun namuna bera olasizmi?
qo'shib qo'ydi muallif michael, manba
RunOnUiThread() Runnable ustida ishlaydi, AsyncTask parametr sifatida qabul qilinmaydi. Har qanday fikr bormi?
qo'shib qo'ydi muallif michael, manba

DoInBackground-da ishlayotganda foydalanuvchi interfeysida o'zgarishlar qilish yoki doInBackground tashqari usullarni o'zgartirish uchun Looper.prepare() yoki runOnUiThread() funksiyasidan foydalaning

Misol:

 runOnUiThread(new Runnable() {
            @Override
            public void run() {
                progressBar = new ProgressDialog(MainActivity.this);
                progressBar.setCancelable(false);
                progressBar.setTitle("Downloading Files...");
                progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                progressBar.setProgress(0);
                progressBar.setMax(100);
                progressBar.show();
            }
        });
2
qo'shib qo'ydi
Javobni tahrirladim.
qo'shib qo'ydi muallif Ashwin Mothilal, manba
Agar Looper.prepare() ishlayotgan bo'lsa, siz bir vaqtning o'zida bir nechta runnables ishlayapsiz. Iltimos, buni tekshirib ko'ring
qo'shib qo'ydi muallif Ashwin Mothilal, manba
Looper.prepare() ishlarga o'xshaydi! UIda o'zgarishlar qilmaganligim sababi nima uchun kerakligini tushunmayapman. (Google qidiruvi UI tarkibiga kiradimi?)
qo'shib qo'ydi muallif michael, manba
runOnUiThread() ishlatish uchun namuna bera olasizmi?
qo'shib qo'ydi muallif michael, manba
RunOnUiThread() Runnable ustida ishlaydi, AsyncTask parametr sifatida qabul qilinmaydi. Har qanday fikr bormi?
qo'shib qo'ydi muallif michael, manba

DoInBackground-da ishlayotganda foydalanuvchi interfeysida o'zgarishlar qilish yoki doInBackground tashqari usullarni o'zgartirish uchun Looper.prepare() yoki runOnUiThread() funksiyasidan foydalaning

Misol:

 runOnUiThread(new Runnable() {
            @Override
            public void run() {
                progressBar = new ProgressDialog(MainActivity.this);
                progressBar.setCancelable(false);
                progressBar.setTitle("Downloading Files...");
                progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                progressBar.setProgress(0);
                progressBar.setMax(100);
                progressBar.show();
            }
        });
2
qo'shib qo'ydi
Javobni tahrirladim.
qo'shib qo'ydi muallif Ashwin Mothilal, manba
Agar Looper.prepare() ishlayotgan bo'lsa, siz bir vaqtning o'zida bir nechta runnables ishlayapsiz. Iltimos, buni tekshirib ko'ring
qo'shib qo'ydi muallif Ashwin Mothilal, manba
runOnUiThread() ishlatish uchun namuna bera olasizmi?
qo'shib qo'ydi muallif michael, manba
Looper.prepare() ishlarga o'xshaydi! UIda o'zgarishlar qilmaganligim sababi nima uchun kerakligini tushunmayapman. (Google qidiruvi UI tarkibiga kiradimi?)
qo'shib qo'ydi muallif michael, manba
RunOnUiThread() Runnable ustida ishlaydi, AsyncTask parametr sifatida qabul qilinmaydi. Har qanday fikr bormi?
qo'shib qo'ydi muallif michael, manba

Men SettableFuture guava orqali qo'ng'iroqni qaytarib berganda asosiy looperga keraksiz kodni ishlatmaslik kerak. (agar sizning qayta qo'ng'iroq qilishingiz og'ir ish yukini boshlasa va UI jankaga olib kelishi mumkin bo'lsa, bu muammo bo'lishi mumkin).

  protected String doInBackground(Void... params) {
      SettableFuture future = SettableFuture.create();
       Log.w(TAG, "before fused call isMainLooper= %b", Looper.getMainLooper().isCurrentThread());
     //future.set runs on the main thread.  
      //future.get stays on the background thread.
      mFusedLocationApi.requestLocationUpdates(
          client,
          LOCATION_REQUEST,
          location1 -> {
             future.set(location1);
      Log.w(TAG, "callback: isMainLooper= %b", Looper.getMainLooper().isCurrentThread());

          }
          Looper.getMainLooper());

      location = future.get(10, SECONDS);
      Log.w(TAG, "after fused call isMainLooper= %b", Looper.getMainLooper().isCurrentThread());

Chiqish chiqishi

W TAG: before fused call isMainLooper = false
W TAG: callback: isMainLooper = true
W TAG: after fused call isMainLooper = false
0
qo'shib qo'ydi

Men SettableFuture guava orqali qo'ng'iroqni qaytarib berganda asosiy looperga keraksiz kodni ishlatmaslik kerak. (agar sizning qayta qo'ng'iroq qilishingiz og'ir ish yukini boshlasa va UI jankaga olib kelishi mumkin bo'lsa, bu muammo bo'lishi mumkin).

  protected String doInBackground(Void... params) {
      SettableFuture future = SettableFuture.create();
       Log.w(TAG, "before fused call isMainLooper= %b", Looper.getMainLooper().isCurrentThread());
     //future.set runs on the main thread.  
      //future.get stays on the background thread.
      mFusedLocationApi.requestLocationUpdates(
          client,
          LOCATION_REQUEST,
          location1 -> {
             future.set(location1);
      Log.w(TAG, "callback: isMainLooper= %b", Looper.getMainLooper().isCurrentThread());

          }
          Looper.getMainLooper());

      location = future.get(10, SECONDS);
      Log.w(TAG, "after fused call isMainLooper= %b", Looper.getMainLooper().isCurrentThread());

Chiqish chiqishi

W TAG: before fused call isMainLooper = false
W TAG: callback: isMainLooper = true
W TAG: after fused call isMainLooper = false
0
qo'shib qo'ydi

Orqa fonda joy olishda muammoga duch keldim. Men Looper.getMainLooper ni qo'shib qo'ygan vaziyatni bilganimda, hujjatlarni qayta o'qishga qaror qildim va fonda joylashgan joyni qanday qilib o'zgartiraman; bu farq FusedLocationProviderClient dan foydalanadi va shunga o'xshash chaqiruvlar.

Avval ko'rsatuvchi provayder mijozingizni belgilang.

private FusedLocationProviderClient mFusedLocationClient;

Define location callbacks, make sure you use com.google.android.gms.location.LocationCallback

/**
 * Fuse location api callback
 */
private LocationCallback mLocationCallback = new LocationCallback() {
    @Override
    public void onLocationResult(LocationResult locationResult) {

        super.onLocationResult(locationResult);

        for (Location location : locationResult.getLocations()) {

            mLastLocation = location;                

            //Send to your server or update your UI

        }
    }

    @Override
    public void onLocationAvailability(LocationAvailability locationAvailability) {

        super.onLocationAvailability(locationAvailability);
        //Send to your server or update your UI

    }
};

Joylashuv yangilanishlarini so'rash uchun bir usulni belgilang

public void startLocationUpdates() {

    boolean hasLocationPermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;

    if (!hasLocationPermission) {
        gettingLocationUpdates = false;
        return;
    }

    mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, /*Looper*/ null);

    com.google.android.gms.tasks.Task task = mFusedLocationClient.getLastLocation();

    task.addOnCompleteListener(task1 -> {

        mLastLocation = task1.getResult();

        gettingLocationUpdates = true;

    });
}

Xizmatni yaratishingiz va yangiliklarni so'rashni boshlang

@Override
public void onCreate() {
    mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
    startLocationUpdates();
}

Joylar yangilanishlarini olib tashlashni unutmang, yoki hech qachon to'xtamaydi

@Override
public void onDestroy() {

if (mFusedLocationClient != null) {
     mFusedLocationClient.flushLocations();                         
   mFusedLocationClient.removeLocationUpdates(mLocationCallback);
}

Bir harakat qilib ko'ring va menga xabar bering.

0
qo'shib qo'ydi

Orqa fonda joy olishda muammoga duch keldim. Men Looper.getMainLooper ni qo'shib qo'ygan vaziyatni bilganimda, hujjatlarni qayta o'qishga qaror qildim va fonda joylashgan joyni qanday qilib o'zgartiraman; bu farq FusedLocationProviderClient dan foydalanadi va shunga o'xshash chaqiruvlar.

Avval ko'rsatuvchi provayder mijozingizni belgilang.

private FusedLocationProviderClient mFusedLocationClient;

Define location callbacks, make sure you use com.google.android.gms.location.LocationCallback

/**
 * Fuse location api callback
 */
private LocationCallback mLocationCallback = new LocationCallback() {
    @Override
    public void onLocationResult(LocationResult locationResult) {

        super.onLocationResult(locationResult);

        for (Location location : locationResult.getLocations()) {

            mLastLocation = location;                

            //Send to your server or update your UI

        }
    }

    @Override
    public void onLocationAvailability(LocationAvailability locationAvailability) {

        super.onLocationAvailability(locationAvailability);
        //Send to your server or update your UI

    }
};

Joylashuv yangilanishlarini so'rash uchun bir usulni belgilang

public void startLocationUpdates() {

    boolean hasLocationPermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;

    if (!hasLocationPermission) {
        gettingLocationUpdates = false;
        return;
    }

    mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, /*Looper*/ null);

    com.google.android.gms.tasks.Task task = mFusedLocationClient.getLastLocation();

    task.addOnCompleteListener(task1 -> {

        mLastLocation = task1.getResult();

        gettingLocationUpdates = true;

    });
}

Xizmatni yaratishingiz va yangiliklarni so'rashni boshlang

@Override
public void onCreate() {
    mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
    startLocationUpdates();
}

Joylar yangilanishlarini olib tashlashni unutmang, yoki hech qachon to'xtamaydi

@Override
public void onDestroy() {

if (mFusedLocationClient != null) {
     mFusedLocationClient.flushLocations();                         
   mFusedLocationClient.removeLocationUpdates(mLocationCallback);
}

Bir harakat qilib ko'ring va menga xabar bering.

0
qo'shib qo'ydi