2015-08-28 2 views
0

Я делаю это приложение, и когда пользователь сначала открывает приложение, я хочу, чтобы только индикатор выполнения работал до тех пор, пока приложение не получит GPS-местоположение пользователя. Затем запустите упражнение, чтобы они могли делать вещи. Но я все время получаю ошибки. Мне было интересно, может ли кто-нибудь действительно помочь мне здесь?Как правильно запустить цикл while в onCreate?

public class MyActivity extends Activity implements View.OnClickListener { 
    private ProgressBar pb = null; 
    @InjectView(R.id.frame) 
    private boolean testrun = false; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     while(!testRun) 
     { 
      setContentView(R.layout.ProgressBar); 
      pb = (ProgressBar) findViewById(R.id.progressBar1); 
      pb.setVisibility(View.VISIBLE); 
      //Then I create an instance of AsyncTask and try to get GPS  
      //coordinates and set testRun to true. 

     } 
     setContentView(R.layout.test); 
     ButterKnife.inject(this); 



    } 

Так что я держать грохот, и оно не даже загрузить на прогресс бар макет ...

+0

Просто установите видимость индикатора выполнения, как только у вас есть место. Нет необходимости в цикле while. Кроме того, в этом коде следует избегать нескольких вещей. – zgc7009

+0

@ zgc7009 Я просто хочу понять свою ошибку, например, почему она падает, когда я помещаю в нее цикл while, что логическая ошибка? – TheQ

+0

@TheQ Ошибка может возникнуть из-за того, что вы создаете AsyncTask внутри цикла while и создаете ее, как тысячу раз или больше.И, как я уже упоминал в своем ответе, вы блокируете поток пользовательского интерфейса, который рано или поздно будет вызывать ошибку. – jfmg

ответ

1

Вам не нужно время цикла в приведенном выше фрагменте кода. Это должно дать вам идею:

Сначала проверьте, включена ли GPS на устройстве, иначе попросите пользователя сделать это.

import android.location.LocationManager; 
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); 
     if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){ 
      showGPSDisabledAlertToUser(); // Write your own code for this 
     } 

Получить широту и долготу (двойные значения):

LocationResult locationResult = new LocationResult(){ 
      @Override 
      public void gotLocation(Location location){ 
       //Got the location! 
       latitude = location.getLatitude(); 
       longitude = location.getLongitude(); 
       new sendRequest().execute(); 
       Log.i("","ALL" + latitude + ":" + longitude); 
      } 
     }; 
     MyLocation myLocation = new MyLocation(); 
     myLocation.getLocation(MainActivity.this, locationResult); 

MyLocation.java файл

import java.util.Timer; 
import java.util.TimerTask; 

import android.content.Context; 
import android.location.Location; 
import android.location.LocationListener; 
import android.location.LocationManager; 
import android.os.Bundle; 

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

    public boolean getLocation(Context context, LocationResult result) 
    { 
     //I use LocationResult callback class to pass location value from MyLocation to user code. 
     locationResult=result; 
     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(), 60000 * 15); 
     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); 
    } 
} 

Вам нужно изменить файл MyLocation, чтобы удалить избыточность на основе ваших потребностей, но это должно дать вам общую идею.

Plus обеспечить все это дело в AsyncTask и show() ProgressDialog в preexecute() и dismiss() после того, как выполнение завершено в postexecute()

Надеются, что это помогает.

+0

LocationListener работает с обратным вызовом. Нет необходимости вставлять его в AsyncTask. – jfmg

+0

@FragmentsNActivities Да, я знаком с этим кодом, очень ценю, но если бы я захотел временно изменить свое содержание до тех пор, пока не будут найдены координаты GPS, это будет сделано в методе getLocation? – TheQ

2

Вы не должны блокировать поток пользовательского интерфейса, так как пользователь больше не сможет взаимодействовать с вашим приложением. Вместо цикла while вы должны показать индикатор ожидания. Например, вы могли бы show a spinning wheel и уволить его, как только вы получили позицию GPS.

Когда ваше приложение выполняет интенсивную работу в ответ на взаимодействие с пользователем, эта модель одного потока может обеспечить низкую производительность, если вы не выполнили свое приложение должным образом. В частности, если все происходит в потоке пользовательского интерфейса, выполнение длительных операций, таких как доступ к сети или запросы к базе данных, заблокирует весь пользовательский интерфейс. Когда поток заблокирован, события не могут быть отправлены, включая события рисования. С точки зрения пользователя приложение, похоже, зависает. Хуже того, если поток пользовательского интерфейса заблокирован более чем на несколько секунд (около 5 секунд в настоящее время), пользователю предоставляется печально известное диалоговое окно «приложение не отвечает» (ANR). Затем пользователь может решить закрыть приложение и удалить его, если они недовольны.

Источник: http://developer.android.com/guide/components/processes-and-threads.html

Edit:
LocationListener работает с обратным вызовом. Нет необходимости вставлять его в AsyncTask. Просто покажите какой-то индикатор ожидания, и как только onLocationChanged будет вызван, вы можете отменить индикатор ожидания.

+1

О, я вижу, поэтому блокирование потока пользовательского интерфейса в любое время - это большой нет. Спасибо за совет, я сделаю это иначе. – TheQ

+0

Вы правы :-) Не блокируйте нить пользовательского интерфейса. Не имеет значения, является ли это Android или другой ОС. Рад, что смог помочь. – jfmg

Смежные вопросы