Android use of an string array on another method - android

Im trying to make an activity that has a multiple choice dialog after you push a button. In there you select from a list of things. But these things are received from a web method before the dialog appears.
So I create a string array after I receive them inside the onCreate to initialise it there with the correct size.
But my dialog method then cant get the array because propably its out of its scope.
My code looks like this
#Override
protected Dialog onCreateDialog(int id)
//Here is where the array is loaded to the multiple select dialog
etc
#Override
public void onCreate(Bundle savedInstanceState)
//Here is where i initialise the array and get its contents
etc
I cant initialise my array when the class starts because I dont know its size yet.
This has to do something with the scopes of my variables and I am pretty confused

make the string array a class member, just populate it in onCreate. You can load it into the dialog in onCreateDialog if the array never changes, if it may change between calls to the dialog then you should do it in onPrepareDialog.
So in your class define:
private String mDialogStrings[];
then in onCreate something like:
mDialogStrings = new String[numItems];
mDialogStrings[0] = string1;
etc...

if you use showDialog and want activity managed dialogs (you should do this) then you must implement onCreateDialog to actually create the dialog. This will get called once for each dialog you have. onPrepareDialog gets called every time you call showDialog(). So the code to update the dialog showing the string array should go in onPrepareDialog and the code to create the dialog should go in onCreateDialog.
public Dialog onCreateDialog(int id) {
switch(id) {
case MY_DIALOG:
Dialog d = new Dialog(this);
return d;
}
}
public void onPrepareDialog(Dialog d, int id) {
switch(id) {
case MY_DIALOG:
d.setSomeStringArray();
break;
}
}

Related

Second dialog is automatically destroyed when created from within a first dialog's OnClickListener

Basically, I have a login screen where users type their email and password to log in. After they have submitted their data, I check if they have confirmed their email address. If not, I display a dialog with a corresponding message. In that dialog I provide them with a neutral button to request a new confirmation email, if they haven't received one yet. If they clicked on that button, I wanna show another dialog with a message that the email has been successfully sent. The problem is that whenever I create and show the second dialog from within the first dialog's OnClickListener, the second dialog is instantiated, but then destroyed immediately. So my question is, why is this happening and how do I implement this kind of functionality so that whatever fragment is being shown will be retained across rotation?
NotVerifiedEmailDialog.java (first dialog):
public class NotVerifiedEmailDialog extends DialogFragment
{
private static final String TAG = "NotVerifiedEmailDialog";
#NonNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.email_not_verified)
.setMessage(R.string.email_not_verified_message)
.setPositiveButton(android.R.string.ok, null)
.setNeutralButton(R.string.request_new_email, new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialogInterface, int which)
{
EmailSentDialog dialog = new EmailSentDialog();
dialog.show(getChildFragmentManager(), dialog.getMyTag());
}
})
.create();
}
public String getMyTag()
{
return TAG;
}
}
EmailSentDialog.java (second dialog):
public class EmailSentDialog extends DialogFragment
{
private static final String TAG = "EmailSentDialog";
#NonNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.success)
.setMessage(R.string.email_sent_message)
.setPositiveButton(android.R.string.ok, null)
.create();
}
public String getMyTag()
{
return TAG;
}
}
Try making the following variable as instance variable. Your dialog object may get destroyed by the previous dialog.
EmailSentDialog dialog;
In case anyone encountered this problem, the solution is to replace getChildFragmentManager() with getParentFragment().getChildFragmentManager(). The former gets a child fragment manager of the first dialog, which is gonna be destroyed, because of the button click (that's why the second dialog is destroyed instantly, because it is tied to the first dialog's child fragment manager), while the latter gets a child fragment manager of the parent fragment (in my case, LoginFragment) and, therefore, is not destroyed immediately.

Android create and initialize window without showing it

I have a dialog with some UI elements in there. This dialog is created and shown at some point later on via show(). I can create the dialog with the default constructor Dialog(Context). But my content view is only set on onCreate which is called after show() function. This causes NPE when I try to modify UI elements like this:
public void showNumber(String number)
{
labelNumber.setText(number);
show();
}
But if call change the above function as below, it works most of the time. (Sometimes it fails if the phone gets slower because setContentView wouldn't be called by the time it executed setText)
public void showNumber(String number)
{
show();
labelNumber.setText(number);
}
How do you create the dialog and set content view without showing it at all. If I call setContentView() manually, it will be re-called when i call show() for the first time.
All you need to do is call create(); on the dialog when you construct it.
When you call show it will create the dialog only if create(); hasn't been called and then call onStart(); on the dialog. Finally it will attach the dialog to the window.
Something like:
Dialog myDialog = new Dialog(context) {
protected void onCreate() {
super.onCreate();
doYourThing
}
};
myDialog.create();
I'm assuming you're doing logic in onCreate, because, in Dialog it's just an empty method for subclasses to override.
onCreate:
http://androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/app/Dialog.java#37
show:
http://androidxref.com/5.1.1_r6/xref/frameworks/base/core/java/android/app/Dialog.java#254
Pre API level 21 (if you can't use an AlertDialog.Builder) you should be able to use onRestoreInstanceState to do what you want to do, like this (this is a hack):
Bundle myBundle = new Bundle();
myBundle.putBoolean("android:dialogShowing", false);
myBundle.putBundle("android:dialogHierarchy", new Bundle());
myDialog.onRestoreInstanceState(myBundle);
Info:
http://androidxref.com/4.4_r1/xref/frameworks/base/core/java/android/app/Dialog.java#411

How to change Show/Remove Dialog and onPrepareDialog for DialogFragments

I'm working on an Android project. I need to use Android 1.6 or above.
My project was working, but now it is showing me some warnings about Dialogs like
"The method dismissDialog(int) from the type Activity is deprecated"
"The method showDialog(int) from the type Activity is deprecated", etc.
So I want to "update" my project to solve these warnings.
I have read and made some test projects to learn about Fragments and DialogFragment.
I have created my own ProgressDialog and I want to use it on my real project, but I have some problems.
public class MyProgressDialog extends DialogFragment {
public MyProgressDialog(){
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Context context = getActivity();
ProgressDialog dialog = new ProgressDialog(context);
Resources resources = context.getResources();
String message = resources.getText(R.string.wait).toString();
dialog.setMessage(message);
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
return dialog;
}
}
Earlier in my project, I created the ProgressDialog and then, in onPrepareDialog() method, I called an AsyncTask to connect the server, downloaded the data, etc. Then in onPostExecute of the AsyncTask, I dismissed the ProgressDialog and started the new Activity. But now I can't do that because onPrepareDialog is deprecated.
Calling ActionAsyncTask on onPrepareDialog of Activy
#Override
protected void onPrepareDialog(int id, Dialog dialog) {
switch(id){
case Constants.PROGRESS_DIALOG:
new ActionAsyncTask().execute();
break;
}
}
onPostExecute of ActionAsyncTask
#Override
protected void onPostExecute(Integer result) {
dismissDialog(Constants.PROGRESS_DIALOG);
}
How can solve this? What is the right way to do this? I want to write the best code for this, the most efficient code.
Thanks.

Closing multiple Dialogs at once

Im writing an Android application in which a user selection triggers a custom Dialog, from which a selection may trigger a second Dialog.
When showing the initial Dialog from the Activity class, I'm setting an onDismissListener on it to pull out user selections which works fine other in cases where the 2nd Dialog is not triggered. The issue that I'm having is that I can't figure out how to have the first one Dialog remain open until the 2nd one is dismissed, so that the information from both is sent back to the Activity class.
Hopefully some code will make this a little more clear:
MainActivity class where I am launching the initial CustomDialog:
customDialog = new CustomDialog(this);
customDialog.show();
customDialog.setOnDismissListener(new OnDismissListener(){
public void onDismiss(DialogInterface di){
slection = customDialog.getselection();
updateUI(); //updates a listview with the results
}
});
Within the CustumDialog class where I am launching the SecondDialog on top of it:
if(specify){
SecondDialog secondDialog = new SecondDialog(context);
secondDialog.show();
secondDialog.setOnDismissListener( new OnDissmissListener(){
public void onDismiss(DialogInterface di){
// this is where I want to call the CustomDialog's dismiss() method
// so that they both close at the same time and the data from here
// can be sent back to the MainActiivty through the CustomDialog's
// onDismissListener
}
});
}
dismiss();
So, to reiterate: I'm trying to prevent the CustomDialog's dismiss() method to be called until the SecondDialog is also dismissed. Is there a way that I can call it from the SecondDialog's OnDismissListener?
You should create customDialog as an instance level variable. You then it will be accessible with onDismiss(...) of second dialog. There you can call customDialog.dismiss();
// Instance level variable
private Dialog customDialog = null;
Instanciate your customDialog, then create second dialog from within your customDialog. Your Second dialog's code would look like this.
if(specify){
SecondDialog secondDialog = new SecondDialog(context);
secondDialog.show();
secondDialog.setOnDismissListener( new OnDissmissListener(){
public void onDismiss(DialogInterface di){
// customDialog is accessible as it is declared as instance level variable
MyClassName.this.customDialog.dismiss();
}
});
}
dismiss();
I prefer to save the data in 1st dialog before going to send one and when dismiss the 2nd dialog, open the 1st dialog again with saved data .. i used this way in my developing and its effective ..

Gettring a reference to a managed ProgressDialog

In my activity I need a ProgressDialog with a horizontal progress bar to visualise the progress of a background task. To make the activity care for the dialog e.g. in case of screen rotation, I would like to use a managed dialog created in onCreateDialog. The problem is that I need to update the progress bar of the dialog after it has been created and therefor I need a reference to the managed progress dialog: Does anyone know how to retrieve a reference to a dialog created by onCreateDialog?
At the moment I am storing a reference to the dialog created in onCreateDialog, but that my fail with a InvalidArgumentException in the onFinished() method after the screen has been rotated (and the activity has been recreated):
public final class MyActivity extends Activity {
private static final int DIALOG_PROGRESS = 0;
private ProgressDialog progressDialog = null;
// [...]
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_PROGRESS:
progressDialog = createProgressDialog();
return progressDialog;
default:
return super.onCreateDialog(id);
}
}
// [...]
public void updateProgress(int progress) {
progressDialog.setProgress(0);
}
public void onFinished() {
progressDialog.dismiss();
}
// [...]
}
I would have expected something like a getDialog(int) method in the Activity class to get a reference to a managed dialog, but this doesn't seem to exist. Any ideas?
I answer myself:
There really is no getDialog(int) method available in the Activity class.
Storing the reference like shown above works correctly -- the bug was something else...
The problem was, that the parallel thread, that called the onFinished() method called this method on the already destroyed activity, thus the accessed ProgressDialog instance is still existing but no longer a valid dialog. Instead another activity with another ProgressDialog has already been created by Android.
So all I needed to do was to make the background thread call the onFinished() method of the new activity and everything works fine. To switch the reference I override the onRetainNonConfigurationInstance() and getLastNonConfigurationInstance() methods of the Activity class.
The good thing of the shown example: Android really cares about recreating the new dialog after the screen orientation changed. So constructing the ProgressDialog that way is definitely easier than using ProgressDialog.show() where I would need to handle the dialog recreation on my own (the two methods described above would be a good place to do this.

Categories

Resources