2015-08-28 54 views
0

我正在製作這個應用程序,當用戶第一次打開應用程序時,我只需要一個進度條,直到應用程序獲取用戶的GPS位置。然後開始活動,以便他們可以做些事情。但我不斷收到錯誤。我想知道是否有人能真正幫助我在這裏?如何在onCreate中正確運行while循環?

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

只要設置進度條的可見性即可消失。不需要一段時間循環。另外,在這段代碼中你應該避免一些事情。 – zgc7009

+0

@ zgc7009我只是想了解我的錯誤,比如爲什麼當我把一個while循環放入時,它會崩潰,什麼是邏輯錯誤? – TheQ

+0

@TheQ錯誤可能會發生,因爲您在while循環內部創建了AsyncTask,並且因此創建了一千次或更多次。而且就像我在我的回答中提到的那樣,您會阻止UI線程,這會遲早會拋出錯誤。 – jfmg

回答

1

你不需要在上面的代碼片段while循環。這應該給你一個想法:

首先看看是否在設備上啓用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文件根據您的需要去除冗餘,但是這應該給你一個總的想法。

加保證這件事是在和的AsyncTask的show()在ProgressDialog的preexecute()dismiss(),一旦執行是在postexecute()

希望這有助於完整。

+0

LocationListener與回調一起使用。沒有必要把它放在一個AsyncTask中。 – jfmg

+0

@FragmentsNActivities是的,我很熟悉那個代碼,非常感謝,但是如果我想暫時改變我的contentview,直到找到GPS座標,那麼這是在getLocation方法中完成的嗎? – TheQ

2

您不應該阻止UI線程,因爲用戶將無法再與您的應用進行交互。而不是while循環,你應該顯示一個等待指示符。例如,您可以show a spinning wheel,並在您獲得GPS位置後立即將其解除。

當您的應用程序爲響應用戶交互而執行大量工作時,除非您正確實施應用程序,否則此單線程模型可能會導致性能較差。具體來說,如果在UI線程中發生了一切,執行諸如網絡訪問或數據庫查詢之類的長操作將會阻塞整個UI。當線程被阻塞時,不會分派任何事件,包括繪圖事件。從用戶的角度來看,應用程序似乎掛起。更糟糕的是,如果UI線程被阻塞超過幾秒(目前約5秒),用戶將看到臭名昭着的「應用程序無響應」(ANR)對話框。如果用戶不滿意,用戶可能會決定退出應用程序並將其卸載。

來源:http://developer.android.com/guide/components/processes-and-threads.html

編輯:
的LocationListener的工作有一個回調。沒有必要把它放在一個AsyncTask中。只需顯示某種等待指示符,一旦調用onLocationChanged,就可以解除等待指示符。

+1

哦,我明白了,所以隨時阻止UI線程是一件很大的事情。感謝諮詢人,我會以不同的方式去做。 – TheQ

+0

你說得對:-)永遠不要阻塞UI線程。不管它是Android還是其他操作系統。很高興我能幫上忙。 – jfmg