Updating a shown Dialog - android

I created a Dialog, using a custom layout:
public class WaitDialog extends DialogFragment {
[..]
#SuppressLint("InflateParams")
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View viewDlg = inflater.inflate(R.layout.dialog_finish, null);
tvStatusMain = (TextView) viewDlg.findViewById(R.id.tvStatusMain);
[..]
}
public void setMessage(String message) {
tvStatusMain.setText(message);
}
}
This code, works fine, but when I instantiate the Dialog like this:
flexWaitDialog = new WaitDialog();
flexWaitDialog.setCancelable(false);
flexWaitDialog.show(this.getFragmentManager(), "login");
and then try to update the message:
flexWaitDialog.setMessage(getString(R.string.initialising));
it shows me the default string from the layout. However, when I use a Handler:
new Handler().post(new Runnable() {
#Override
public void run() {
flexWaitDialog.setMessage(getString(R.string.initialising));
}
});
it does work. Is there a reason for this hoop-jumping? And if not, is there a better way?

I think, onResume is called before onCreateDialog.
You can modify your class to handle that:
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View viewDlg = inflater.inflate(R.layout.dialog_finish, null);
tvStatusMain = (TextView) viewDlg.findViewById(R.id.tvStatusMain);
if (mMessage != null) {
tvStatusMain.seText(mMessage);
}
mViewCreated = true;
[..]
}
public void setMessage(String message) {
if (mViewCreated) {
tvStatusMain.setText(message);
} else {
mMessage = message
}
}

Related

Sending data from Dialog to Fragment

I am trying to send some data from a DialogFragment to a TextView from a Fragment.
After inserting the data in the available input and pressing SAVE, the app crashes.
I assume there is something wrong with the IncomeDialogListener.
I would appreciate some hints where I did wrong.
This is the Dialog Class
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.layout_incomedialog, null);
builder.setView(view)
.setTitle("Add Income")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("Save", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String Amount = enter_income_amount.getText().toString();
String Note = enter_income_note.getText().toString();
String Date = enter_income_date.getText().toString();
incomeDialogListener.addDetails(Amount, Note, Date);
}
});
enter_income_amount = view.findViewById(R.id.enter_income_amount);
enter_income_note = view.findViewById(R.id.enter_income_note);
enter_income_date = view.findViewById(R.id.enter_income_date);
return builder.create();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
incomeDialogListener = (IncomeDialogListener) getTargetFragment();
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + "Must Implement IncomeDialogListener");
}
}
public interface IncomeDialogListener {
void addDetails(String Amount, String Note, String Date);
}
This is the Fragment to which I want to send the data
public class IncomeFragment extends Fragment implements
IncomeDialog.IncomeDialogListener {
DatabaseHelper myDB;
Button btn_add_income;
TextView display_income;
public IncomeFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_placeholder2 , container, false);
display_income = (TextView) v.findViewById(R.id.display_income);
btn_add_income = (Button) v.findViewById(R.id.btn_add_income);
myDB = new DatabaseHelper(getActivity());
btn_add_income.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openIncomeDialog();
}
});
return v;
}
private void openIncomeDialog() {
android.support.v4.app.FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
IncomeDialog incomeDialog = new IncomeDialog();
incomeDialog.show(fragmentTransaction, "income dialog" );
}
#Override
public void addDetails(String Amount, String Note, String Date) {
display_income.setText(Amount);
}
}
Here is my solution for you:
IncomeFragment.java
public static final int INCOME_DIALOG_FRAGMENT = 1; // Add this line
private void openIncomeDialog() {
android.support.v4.app.FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
IncomeDialog incomeDialog = new IncomeDialog();
incomeDialog.setTargetFragment(IncomeFragment.this, INCOME_DIALOG_FRAGMENT); // Add this line
incomeDialog.show(fragmentTransaction, "income dialog");
}
IncomeDialog.java
#Override
public void onClick(DialogInterface dialog, int which) {
String Amount = enter_income_amount.getText().toString();
String Note = enter_income_note.getText().toString();
String Date = enter_income_date.getText().toString();
IncomeDialogListener listener = (IncomeDialogListener) getTargetFragment();
listener.addDetails(Amount, Note, Date);
}
Update: There is no magic behind, when you open dialog from fragment, you passed itself to dialog by calling setTargetFragment. Then in the dialog you can refer to the fragment that opened it by calling getTargetFragment. Actually there are 2 solutions you can use.
IncomeFragment incomeFragment = (IncomeFragment) getTargetFragment();
incomeFragment.addDetails(Amount, Note, Date);
or
IncomeDialogListener listerner = (IncomeDialogListener) getTargetFragment();
listerner.addDetails(Amount, Note, Date);
I prefer to use the second one because the dialog don't need to know about specific fragment that opened it. This makes the dialog is usable. Imagine a situation, three days later, you would like to open the dialog from another fragment, in that case you don't need to modify the dialog again, just let the another fragment implements IncomeDialogListener. If you use the first one, you must go to the dialog and modify it to make sure it works for the another fragment.

How to create a popup when button is pushed in Android?

How can I create a custom popup class that accepts a simple string message? Im new to Android and help with code will be appreciated.
When a button is pushed in the main layout, the popup must pop up on the screen.
Custom popup class
public class CustomPopup extends PopupWindow {
private String message;
private Double anchorX;
private Double anchorY;
PopupWindow popup;
public CustomPopup(String message) {
super();
this.message = message;
}
public void showPopup(Activity context) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
}
Main Class
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText messageTxt = (EditText) findViewById(R.id.messageTxt);
Button generateBtn = (Button) findViewById(R.id.generateBtn);
String message = messageTxt.getText().toString();
final CustomPopup popup = new CustomPopup(message);
generateBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
popup.showPopup();
}
});
}
}
You can change the following code any way you need. This is just an example of how you make and implement a custom DialogFragment.
He is the code I use. I find it quite flexible because you can create several similar dialogs for slightly different tasks. You will need to create a layout file - this gives you a great deal of flexibility on function and style.
My layout file is fragment_ok_cancel_dialog.
To satisfy your requirements just create your own layout file with all the elements in it you need (like your image).
In the Activity that calls the dialog you will need to implement the Listener.
implements OkCancelDialogFragment.OkCancelDialogListener
Another advantage is with my code you can change the title and the message to fit the needs of any Activity.
private void callMyDialog(){
//Customize the title and message as needed
String title = "This is my dialog title";
String mess = "This is my dialog message";
OkCancelDialogFragment dialog = OkCancelDialogFragment.newInstance(title, mess);
dialog.show(getFragmentManager(), "OkCancelDialogFragment2");
}
Now you need to implement the dialog callback in the Activity that calls the DialogFragment.
#Override
public void onFinishOkCancelDialog(boolean submit) {
if(submit){
// Do something positive
}
else{
// Do something negative
}
}
Now the code for the DialogFragment:
public class OkCancelDialogFragment extends DialogFragment {
private static final String ARG_TITLE = "title";
private static final String ARG_MESSAGE = "message";
Context context = null;
private String title;
private String message;
private boolean submitData = false;
private OkCancelDialogListener mListener;
public OkCancelDialogFragment() {
}
public static OkCancelDialogFragment newInstance(String title, String message) {
OkCancelDialogFragment fragment = new OkCancelDialogFragment();
Bundle args = new Bundle();
args.putString(ARG_TITLE, title);
args.putString(ARG_MESSAGE, message);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
title = getArguments().getString(ARG_TITLE);
message = getArguments().getString(ARG_MESSAGE);
}
}
#Override
public Dialog onCreateDialog(Bundle saveIntsanceState){
context = getActivity();
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
View rootView = inflater.inflate(R.layout.fragment_ok_cancel_dialog, null, false);
final TextView titleView = (TextView)rootView.findViewById(R.id.tvTitle);
final TextView messView = (TextView)rootView.findViewById(R.id.tvMessage);
titleView.setText(title);
messView.setText(message);
builder.setView(rootView)
// .setTitle(title)
.setPositiveButton(R.string.ok_button_dialog_title, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
submitData = true;
if(mListener == null) mListener = (OkCancelDialogListener) context;
mListener.onFinishOkCancelDialog(submitData);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
submitData = false;
if(mListener == null) mListener = (OkCancelDialogListener) context;
mListener.onFinishOkCancelDialog(submitData);
}
});
return builder.create();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
if(mListener == null) mListener = (OkCancelDialogListener) context;
}
catch (Exception ex){
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OkCancelDialogListener {
void onFinishOkCancelDialog(boolean submit);
}
}
Please note that .setTitle(title) is valid for API 23 or higher (or maybe API 21 or higher?).
You can create your custom xml layout
and in the OnClickListener of the button you can put this :
LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
alertLayout = inflater.inflate(R.layout.YOUR_CUSTOM_POPUP_LAYOUT, null);
final AlertDialog alert = new AlertDialog.Builder(this).create();
alert.setView(alertLayout);
TextView msg= alertLayout.findViewById(R.id.YOUR_TEXTVIEW_ID);
alert.show();
after that you can add another button in your popup and set a listener on it to dismiss the layout after the click.

Why doesn't progress spinner work after closing alert dialog in android?

My progress bar is just a spinner.
I am showing two options to user and when user clicks an option, I show a dialog, so that user reads and understands it.
This is what I want.
When they click positive, it should show the spinner and keep calling service on background.
When they click negative, it should make the option unchecked.
Here is the code.
This radioGroup.setOnClickListener goes into onCreateView method of a fragment.
public class Choose_CountryFragment extends Fragment {
private RadioGroup radioGroup;
private TextView textView;
private String countryChosen = null;
ConnectionStatus connectionStatus = new ConnectionStatus(getContext());
public Choose_CountryFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
final Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_choose__country, container, false);
radioGroup = (RadioGroup) rootView.findViewById(R.id.country_choice_radio);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener()
{
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch(checkedId){
case R.id.countryCanada:
// do operations specific to this selection
countryChosen = "Canada";
Intent explicitServiceIntent = new Intent(getActivity(), Service.class);
explicitServiceIntent.putExtra("country", "Canada");
getActivity().startService(explicitServiceIntent);
connectionStatus.showProgress();
break;
case R.id.countryUSA:
countryChosen = "USA";
Dialog dialog = onCreateDialog(savedInstanceState);
dialog.show();
connectionStatus.showProgress();
break;
}
}
});
public Dialog onCreateDialog(final Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
Toast.makeText(getContext(), "Click Got it", Toast.LENGTH_LONG).show();
builder.setMessage(R.string.SignUpWarningInfo)
.setPositiveButton(R.string.gotIt, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent explicitServiceIntentUSA = new Intent(getActivity(), Service.class);
explicitServiceIntentUSA.putExtra("country", countryChosen );
getActivity().startService(explicitServiceIntentUSA);
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
return;
}
});
// Create the AlertDialog object and return it
return builder.create();
}
}
}
ConnectionStatus.java
public class ConnectionStatus {
private Context _context;
private ProgressDialog progressDialog = null;
public ConnectionStatus(Context context) {
this._context = context;
}
public void showProgress(){
progressDialog = new ProgressDialog(_context);
progressDialog.setCancelable(false);
progressDialog.setIndeterminate(true);
progressDialog.show();
}
}
Error happens when I click USA.
Error I get
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources$Theme android.content.Context.getTheme()' on a null object reference
at android.app.AlertDialog.resolveDialogTheme(AlertDialog.java:154)
at android.app.AlertDialog.<init>(AlertDialog.java:109)
at android.app.ProgressDialog.<init>(ProgressDialog.java:77)
at com.a2.a2.ConnectionStatus.showProgress(ConnectionStatus.java:66)
at com.a2.a2.signUp.Choose_CountryFragment$1.onCheckedChanged(Choose_CountryFragment.java:73)
Your Context returning null
Change code in Choose_CountryFragment
public class Choose_CountryFragment extends Fragment {
...
protected Context mContext;
private ConnectionStatus connectionStatus
...
public Choose_CountryFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
final Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_choose__country, container, false);
...
connectionStatus = new ConnectionStatus(mContext);// initialize ConnectionStatus here
...
}
}
Override onAttach Inside Choose_CountryFragment
#Override
public void onAttach(Context context) {
super.onAttach(context);
mContext = context;
}
In Fragment, you have to use:
ProgressDialog progressDialog = new ProgressDialog(getActivity);
From the documentation, the getActivity() method returns the Activity this Fragment is currently associated with it.
Edit:
In Activity class, you have to use like:
ProgressDialog progressDialog = new ProgressDialog(YourActivityClassName.this);

Creating listener of a CustomDialog out of the class in Android

I am trying to create a listener of a button of a customdialog which extends DialogFragment class and I want to locate the listener of custom buttons out of customdialog fragment class .However when I try to call the view of CustomDialog Fragment then I am getting null exception. What I do is to create an new instance of the customdialog fragment in somewhere else and say
customdialog.getView().findViewById(R.id.custombutton);
but I am getting null.
public class CustomDialog extends DialogFragment {
public final int RES_NONE = -1;
private TextViewCustomFont dialogTitle, view2, dialogBodyBottom,
dialogBodyTop;
private EditTextCustomFont dialogEditText;
private ButtonCustomFont dialogLeftButton;
private ButtonCustomFont dialogRightButton;
private Typeface GothamBold, GothamMedium, GothamUltra;
private static int title1, bodyTop1, bodyBottom1, EditTextHint1,
leftButton1, rightButton1;
onSubmitListener mListener;
private Dialog dialog;
interface onSubmitListener {
void setOnSubmitListener(String arg);
}
public static CustomDialog newInstance(int title, int bodyTop,
int bodyBottom, int EditTextHint, int leftButton, int rightButton) {
title1 = title;
bodyTop1 = bodyTop;
bodyBottom1 = bodyBottom;
EditTextHint1 = EditTextHint;
leftButton1 = leftButton;
rightButton1 = rightButton;
CustomDialog frag = new CustomDialog();
return frag;
}
public ButtonCustomFont getDialogLeftButton() {
return dialogLeftButton;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
dialog = new Dialog(getActivity());
dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
//dialog.setContentView(R.layout.dialog_layout);
//dialog.show();
initLayout();
return dialog;
}
private void initLayout(){
dialog.setContentView(R.layout.dialog_layout);
setDialogView();
setCustomDialog();
}
public void setDialogView(){
//Create an java object of each dialog view item
dialogTitle = (TextViewCustomFont) dialog.findViewById(R.id.custom_dialog_title);
dialogBodyTop = (TextViewCustomFont) dialog.findViewById(R.id.custom_dialog_body_top);
dialogBodyBottom = (TextViewCustomFont) dialog.findViewById(R.id.custom_dialog_body_bottom);
dialogEditText = (EditTextCustomFont) dialog.findViewById(R.id.custom_dialog_body_et);
dialogLeftButton = (ButtonCustomFont) dialog.findViewById(R.id.custom_dialog_body_btn_left);
dialogRightButton = (ButtonCustomFont) }
public class LoginSelectionFragment extends Fragment {
public static LoginSelectionFragment newInstance() {
LoginSelectionFragment fragment = new LoginSelectionFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_loginselection,
container, false);
}
I am trying to pull the dialogLeftButton of CustomDialog Fragment and assing a listener on it inside the LoginSelectionFragment.
Here is how it looks like after I added method 2. This a part of LoginSelectionFragment
private void TwoButtonTextEditTextDialog(){
String title = getResources().getString(R.string.invalid_info_header);
String body = getResources().getString(R.string.invalid_info_body);
String body2 = getResources().getString(R.string.hint_newemail);
String btn1 = getResources().getString(R.string.cancel_uppercase);
String btn2 = getResources().getString(R.string.ok_alert);
fragmentDialog = CustomDialog.newInstance(title, body, body2, RES_NONE, btn1, btn2);
fragmentDialog.setCustomDialogFragmentListener(mDialogClickListener);
fragmentDialog.show(getFragmentManager(), "");
}
private CustomDialog.CustomDialogFragmentListener mDialogClickListener = new CustomDialog.CustomDialogFragmentListener(){
#Override
public void onNegativeClick() {
// TODO Auto-generated method stub
fragmentDialog.dismiss();
}
#Override
public void onPositiveClick() {
// TODO Auto-generated method stub
fragmentDialog.dismiss();
}
};
#Override
public void onNegativeClick() {
// TODO Auto-generated method stub
}
#Override
public void onPositiveClick() {
// TODO Auto-generated method stub
}
You could create a method as setDialogButtonClickListener(CustomDialog.OnButtonClickListener clickListener); where CustomDialog.OnButtonClickListener is an inner static interface , that way you could listen to click events of the buttons from anywhere.
An example of this could look as below,
public class CustomDialog extends DialogFragment {
.....
public static CustomDialog newInstance(int title, int bodyTop,
int bodyBottom, int EditTextHint, int leftButton, int rightButton) {
CustomDialog frag = new CustomDialog();
Bundle args = new Bundle();
args.putInt("title", title);
......
frag.setArguments(args);
return frag;
}
...
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int title = getArguments().getInt("title");
return new AlertDialog.Builder(getActivity())
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle(title)
.setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, this)
....
.create();
}
#Override
public void onClick(DialogInterface dialog, int which) {
if (listener != null) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
listener.onRightButtonClick();
default:
listener.onLeftButtonClick();
}
}
}
...
private CustomDialog.OnButtonClickListener mClickListener;
....
public void setDialogButtonClickListener(CustomDialog.OnButtonClickListener clickListener){
mClickListener = clickListener;
}
...
public static interface OnButtonClickListener {
public void onLeftButtonClick();
public void onRightButtonClick();
}
}
If you notice from the above sample I posted , I have besides solving your problem of setting the click listener on buttons also have introduced you with the Factory Design Pattern on Android , You can see that instead of creating static fields for the button title and Dialog title I've set them in the Bundle Argument and then Retrieve them in the Dialogs onCreate() method.
For more Best Practices of Fragment You can take a look here
Edit
Ok , for your help I am providing you a Glimpse of what your LoginSelectionFragment should look like.
public class LoginSelectionFragment extends Fragment implements CustomDialog.OnButtonClickListener {
......// Method 1
public void showDialog(String title , String message .....) {
CustomDialog dialog = CustomDialog.getInstance(title , message...);
dialog.setDialogButtonClickListener(this);
dialog.show(getSupportFragmentManager(), null);
}
public void onLeftButtonClick(){
...// do something on left button click of dialog
}
public void onRightButtonClick(){
// do something on right button click of dialog
..
}
// Method 2
public void showDialog2(String title , String message .....) {
CustomDialog dialog = CustomDialog.getInstance(title , message...);
dialog.setDialogButtonClickListener(mDialogClickListener);
dialog.show(getSupportFragmentManager(), null);
}
private final CustomDialog.OnButtonClickListener mDialogClickListener = new CustomDialog.OnButtonClickListener() {
public void onLeftButtonClick(){
...// do something on left button click of dialog
}
public void onRightButtonClick(){
// do something on right button click of dialog
..
}
}
}
Now If you look at Method 1 , we have given parameters to showDialog() method so that you could reuse it for showing multiple times with different arguments ie., you could use this approach when you want to show the same dialog with different title , message etc
and in Method 2 we have provided an anonymous inner class for handling click events you could as many anonymous inner classes as you have different varieties of dialog ie dialog with different UI and different Event listeners in the same activity/fragment.
Enjoy!
Try to use this, (did not test this)
public class MyDialogFragment extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.input_warning)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
return builder.create();
}
}
and in your Activity fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.workout_a_fragment, container, false);
Button button = (Button)view.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fm = getActivity().getFragmentManager();
MyDialogFragment dialog = new MyDialogFragment();
dialog.show(fm, DIALOG_WARNING);
}
});}

Error adding objects to public arraylist in android application

I've extended Application and declared a public ArrayList there that I use to hold data (I know it's not as a Singleton in android should be, but it was the only thing I could make work).
The problem :
When I display my CreateNewObject dialog and press OK I get the following error.
Error:
10-30 10:20:19.069: E/AndroidRuntime(632): java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(16908298, class android.widget.ListView) with Adapter(class com.nuclear.gfr.adapter.PatientAdapter)]
My code:
public class NewPatientDialog extends DialogFragment {
private static final String TAG = "NUKClear";
OnNewPatientlistener listener;
private NewPatientDialog() {
}
public interface OnNewPatientlistener {
public void OnNewPatient(Patient newPatient);
}
public void addPatientAction(Patient patient) {
OnNewPatientlistener activity = (OnNewPatientlistener) getActivity();
activity.OnNewPatient(patient);
}
public static NewPatientDialog newInstance(String title) {
NewPatientDialog frag = new NewPatientDialog();
Bundle args = new Bundle();
args.putString("title", title);
frag.setArguments(args);
return frag;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
String title = getArguments().getString("title");
LayoutInflater inflater = (LayoutInflater) getActivity()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View newPatient = inflater.inflate(R.layout.new_patient_dialog,
null);
Log.d(TAG, "Creating dialog for new patientinput...");
return new AlertDialog.Builder(getActivity())
.setIcon(R.drawable.alert_dialog_icon)
.setTitle(title)
.setView(newPatient)
.setPositiveButton(R.string.alert_dialog_ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
final EditText name = (EditText) newPatient
.findViewById(R.id.name_edit);
final EditText ssn = (EditText) newPatient
.findViewById(R.id.ssn_edit);
final EditText accnum = (EditText) newPatient
.findViewById(R.id.accnr_edit);
final Patient patient = new Patient(ssn.getText()
.toString(), name.getText().toString(),
new Study(SimpleDateFormat
.getDateInstance().toString(),
accnum.getText().toString()));
addPatientAction(patient);
DatabaseHelper db = new DatabaseHelper(
getActivity());
db.addPatientStudy(patient);
/*DataManager dm = new DataManager(getActivity()
.getBaseContext());
dm.addPatient(patient);*/
/*
* PatientManager pm = new
* PatientManager(getActivity
* ().getBaseContext()); pm.add(patient);
*/
// Interfacecallback
/*
* OnNewPatientlistener activity =
* (OnNewPatientlistener) getActivity();
* activity.OnNewPatient(patient);
*/
}
})
.setNegativeButton(R.string.alert_dialog_cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
dismiss();
}
}).create();
}
}
Can anyone explain why this happens and how to circumvent this?
Adding...
runOnUiThread(new Runnable() {
public void run() {
GFRApplication.dPatients.add(newPatient);
}
});
...did the trick.

Categories

Resources