2012-08-12 72 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. 
//=============================================================================