2012-08-12 73 views
1

這確實讓我陷入了困境,在我的Android應用程序中點擊Button時,似乎這些方法被稱爲不同步。當我點擊Button下面我想打電話:Android撥打電話的方法

loc = new Location(Options.this); 

一旦完成,然後我想打電話:

setLocationPref(); 

在現實中會發生什麼事是,當我的程序進入下面的「displayLocations方法「再次跳回按鈕,並呼籲:

setLocationPref(); 

我認爲錯誤在於對兩行代碼:

builder.setItems(cs, new DialogInterface.OnClickListener(){ 
    public void onClick(DialogInterface dialog, int item){ 

如果任何人有任何想法,請讓我知道,非常感謝:)

/** Location selection */ 
bLocation = (Button) findViewById(R.id.bLocation); 
bLocation.setOnClickListener(new View.OnClickListener() { 
    public void onClick(View v) { 

     loc = new Location(Options.this); 

     loc.locationSelection(); 

     setLocationPref(); 
    } 
}); 

代碼轉回,我已經寫/ **失敗HERE */

/** Display locations in a list */ 
public void displayLocations(){ 

Log.d("displayLocations", "displayLocations "); 

LocationSQL getSetLocation = new LocationSQL(context); 

final ArrayList<String> locations = locSQL.allLocations(); 
final CharSequence[] cs = locations.toArray(new CharSequence[locations.size()]); 
AlertDialog.Builder builder = new AlertDialog.Builder(context); 
builder.setTitle("Pick your location."); 
builder.setItems(cs, new DialogInterface.OnClickListener(){ 
    public void onClick(DialogInterface dialog, int item){ 

     /** FAILS HERE */ 

     Toast.makeText(context, cs[item], Toast.LENGTH_SHORT).show(); 
     String selectedLocation = locations.get(item); 
     updateLocationInfo(selectedLocation); 
    } 
}); 
builder.create().show(); 
} 

回答

1

我認爲你需要記住,在Android對話框中不是以串行方式處理的。例如。當我在個人電腦上編寫我的SWT應用程序時,我可以等到對話被迴應後,然後回去做下一步做的事情。在Android中不是這樣。你會立即顯示一個對話框並繼續生活。因此,可能發生的是:

您對loc.locationSelection()的調用調用displayLocations()。當displayLocations()開始執行它的工作時,按鈕偵聽器中的控件轉到它的下一個任務,即setLocationPref();

另一個重要的事情是,在Android中,你不應該真正嘗試顯示自己的對話框,就像你在做什麼一樣,因爲這不會處理屏幕旋轉時的狀態更改或用戶在應用程序與其他應用程序之間切換時的狀態更改,您的應用暫停(殺死)一段時間。您需要在onCreateDialog()中創建警報,然後在onPrepareDialog()中進行準備,並使用showDialog()顯示對話框 - 至少這是直到最近纔出現,直到DialogFragment出現爲止(請參見下文)。然後操作系統會處理剩下的事 - 你需要信任它。

不要直接在對話框中調用.show()!系統會爲你做。

請注意,這種做事方式已被DialogFragment取代。但是,我認爲對於任何人來說,至少有一次這樣做是好的和教育的。這是我爲自己寫的一篇評論,旨在瞭解狀態變化以及如何在DialogFragment之前以常規方式處理對話。我希望它有幫助。

//============================================================================= 
// Note re. handling of application kill, screen rotation and other state 
// change events: 
// 
// Android will re-execute the onCreate() method for such events. 
// Actually, the whole object gets re-created even for a screen rotation! 
// If you put a static counter in the constructor, you will see that the 
// constructor gets re-executed and all the non-static variables get scrapped 
// and re-created. The saving grace is that the rotation or other such events 
// do not immediately interrupt when you are in the middle of executing a 
// method, but rather it gets queued to be handled when its turn comes (or so 
// I hope, else there would have chaos). 
// Thus data consistency is not threatened and we can plan to recover from 
// such situations gracefully. 
// 
// The only data that is safe is static class data, or you can - or rather 
// should 
// - save data as Android advises, by means of 
//  onRetainNonConfigurationInstance() and 
//  getLastNonConfigurationInstance() 
// (deprecated in API 13 and replaced by 
//  setRetainInstance(boolean)). 
// Note that to save data across complete application restart from a cold 
// kill you would need to use: 
//  onSaveInstanceState() and 
//  onRestoreInstanceState(). 
// See 
// http://developer.android.com/guide/topics/resources/runtime-changes.html). 
// 
// Using statics is probably OK if you are feeling a bit lazy. 
// It will probably take care of the state changes, but not of the complete 
// kill, of course. 
// 
// If doing it the proper way, however, we use a clear and simple contract 
// with the OS: 
// 
// 1. We need to save/restore our data before/after a state change or being 
// suspended. We do this using onRetainNonConfigurationInstance(), 
// getLastNonConfigurationInstance() for state changes - or equivalent 
// dialog fragment functionality - and using onSaveInstanceState() and 
// onRestoreInstanceState() for application being suspended. 
// 
// 2. We also need to ensure that all onCreateDialog() and 
// onPrepareDialog() methods (or their equivalents, if using the dialog 
// fragment API) can be meaningfully executed on the application being 
// re-constituted after a state change or after being suspended and 
// re-activated. The OS will execute onCreateDialog() always on 
// application re-activation, and will execute onPrepareDialog() if the 
// dialog was opened at the time the state change or application suspension 
// took place (or if it was opened at any time in the past - see below!) 
// 
// 3. Therefore all data that is required for re-constituting dialogs 
// (for onCreateDialog() and onPrepareDialog() if this model is used in 
// preference to dialog fragment), must be available all the time and must 
// be saved in onRetainNonConfigurationInstance() and in 
// onSaveInstanceState(). 
// 
// 4. It also means that we cannot re-use or clean any variables whose 
// function Is to 'deliver' information to e.g. onPrepareDialog(). If 
// these variables are re-initialized or otherwise overwritten after the 
// dialog has been displayed, they will not be available when the OS 
// attempts to re-run these methods to re-constitute the dialog! 
// 
// WARNING: 
// Remember not to try to prevent the re-creation of these dialogs or 
// otherwise hand onto those dialog instances (e.g. by means of static 
// variables), because they are likely to reference your screen GUI and if 
// you use the old (eg. pre-rotation) instances, they will try to reference 
// non-existing variables from the old instance of the application, and things 
// might get funny and actually crash. 
// 
// IMPORTANT: 
// Also note that during such re-creations of the screen, user input fields 
// (fields that are user-writable) on the screen will NOT be overwritten, even 
// if we try to overwrite them. This is good, because it means that if we 
// preserve our read-only data over the rotation, the system will preserve 
// whatever the user might have typed in. 
// 
// NOTE: 
// Additional note re. onPrepareDialog() 
// (This actually might be a bug in Android) 
// 
// It seems the Android will call onPrepareDialog() on screen rotation, even if 
// the dialog is not currently displayed. Perhaps it will also be called at 
// other times. It does not seem to be called on normal app startup or on app 
// re-creation after it is suspended, but best to be safe and assume that the 
// method will be generally called immediately after onCreateDialog() even if 
// the dialog is not active (displayed). 
// 
// Therefore: 
// - All data that the onPrepareDialog() needs must always be provided or 
// suitable dummy substitutes must be given or the method should quietly exit 
// early if such data is not found. 
// - The dialog must not try to do any actions that affect the main 
// application data, unless the data we have for it is real and we are sure 
// that the dialog is really going to be displayed: Such actions are perhaps 
// not common but one could conceivably put such actions in onPrepareDialog() 
// (in places other than listeners, where such actions are common place), but 
// if we use dummy data or exit early, such actions will obviously be 
// nonsensical. 
// 
// However, the whole scheme of using onCreateDialog/onPrepareDialog has been 
// deprecated and therefore will not be fixed even if this thing here 
// is an error. 
//=============================================================================